Jelajahi Sumber

Use promises to determine when to create the controlbox

JC Brand 8 tahun lalu
induk
melakukan
694eabfc0e

+ 90 - 25
spec/register.js

@@ -3,20 +3,42 @@
 } (this, function ($, jasmine, mock, converse, test_utils) {
     var Strophe = converse.env.Strophe;
     var $iq = converse.env.$iq;
+    var _ = converse.env._;
 
     describe("The Registration Panel", function () {
 
-        it("is not available unless allow_registration=true",  mock.initConverse(function (_converse) {
+        it("is not available unless allow_registration=true",
+            mock.initConverseWithPromises(
+                null, ['connectionInitialized', 'chatBoxesInitialized'],
+                { auto_login: false,
+                  allow_registration: false },
+                function (done, _converse) {
+
+            test_utils.waitUntil(function () {
+                    return _converse.chatboxviews.get('controlbox');
+                }, 300)
+            .then(function () {
+
             test_utils.openControlBox();
             var cbview = _converse.chatboxviews.get('controlbox');
             expect(cbview.$('#controlbox-tabs li').length).toBe(1);
             expect(cbview.$('#controlbox-tabs li').text().trim()).toBe("Sign in");
-
-            }, { auto_login: false,
-                 allow_registration: false,
+            done();
+            });
         }));
 
-        it("can be opened by clicking on the registration tab", mock.initConverse(function (_converse) {
+        it("can be opened by clicking on the registration tab",
+            mock.initConverseWithPromises(
+                null, ['connectionInitialized', 'chatBoxesInitialized'],
+                { auto_login: false,
+                  allow_registration: true },
+                function (done, _converse) {
+
+            test_utils.waitUntil(function () {
+                    return _.get(_converse.chatboxviews.get('controlbox'), 'registerpanel');
+                }, 300)
+            .then(function () {
+
             var cbview = _converse.chatboxviews.get('controlbox');
             test_utils.openControlBox();
             var $tabs = cbview.$('#controlbox-tabs');
@@ -32,12 +54,22 @@
             expect($login.is(':visible')).toBe(false);
             expect($registration.is(':visible')).toBe(true);
             expect(cbview.switchTab).toHaveBeenCalled();
-
-            }, { auto_login: false,
-                 allow_registration: true,
+            done();
+            });
         }));
 
-        it("allows the user to choose an XMPP provider's domain", mock.initConverse(function (_converse) {
+        it("allows the user to choose an XMPP provider's domain",
+            mock.initConverseWithPromises(
+                null, ['connectionInitialized', 'chatBoxesInitialized'],
+                { auto_login: false,
+                  allow_registration: true },
+                function (done, _converse) {
+
+            test_utils.waitUntil(function () {
+                    return _.get(_converse.chatboxviews.get('controlbox'), 'registerpanel');
+                }, 300)
+            .then(function () {
+
             var cbview = _converse.chatboxviews.get('controlbox');
             var registerview = cbview.registerpanel;
             spyOn(registerview, 'onProviderChosen').and.callThrough();
@@ -59,11 +91,22 @@
             $form.find('input[type=submit]').click();
             expect(registerview.onProviderChosen).toHaveBeenCalled();
             expect(_converse.connection.connect).toHaveBeenCalled();
-        }, { auto_login: false,
-              allow_registration: true,
-            }));
+            done();
+            });
+        }));
+
+        it("will render a registration form as received from the XMPP provider",
+            mock.initConverseWithPromises(
+                null, ['connectionInitialized', 'chatBoxesInitialized'],
+                { auto_login: false,
+                  allow_registration: true },
+                function (done, _converse) {
+
+            test_utils.waitUntil(function () {
+                    return _.get(_converse.chatboxviews.get('controlbox'), 'registerpanel');
+                }, 300)
+            .then(function () {
 
-        it("will render a registration form as received from the XMPP provider", mock.initConverse(function (_converse) {
             var cbview = _converse.chatboxviews.get('controlbox');
             cbview.$('#controlbox-tabs').find('li').last().find('a').click(); // Click the Register tab
             var registerview = _converse.chatboxviews.get('controlbox').registerpanel;
@@ -107,14 +150,25 @@
             expect(registerview.$('input').length).toBe(5);
             expect(registerview.$('input[type=submit]').length).toBe(1);
             expect(registerview.$('input[type=button]').length).toBe(1);
-        }, { auto_login: false,
-              allow_registration: true,
-            }));
+            done();
+            });
+        }));
+
+        it("will set form_type to legacy and submit it as legacy",
+            mock.initConverseWithPromises(
+                null, ['connectionInitialized', 'chatBoxesInitialized'],
+                { auto_login: false,
+                  allow_registration: true },
+                function (done, _converse) {
+
+            test_utils.waitUntil(function () {
+                    return _.get(_converse.chatboxviews.get('controlbox'), 'registerpanel');
+                }, 300)
+            .then(function () {
 
-        it("will set form_type to legacy and submit it as legacy", mock.initConverse(function (_converse) {
             var cbview = _converse.chatboxviews.get('controlbox');
             cbview.$('#controlbox-tabs').find('li').last().find('a').click(); // Click the Register tab
-            var registerview = _converse.chatboxviews.get('controlbox').registerpanel;
+            var registerview = cbview.registerpanel;
             spyOn(registerview, 'onProviderChosen').and.callThrough();
             spyOn(registerview, 'getRegistrationFields').and.callThrough();
             spyOn(registerview, 'onRegistrationFields').and.callThrough();
@@ -156,11 +210,22 @@
             var $stanza = $(_converse.connection.send.calls.argsFor(0)[0].tree());
             expect($stanza.children('query').children().length).toBe(3);
             expect($stanza.children('query').children()[0].tagName).toBe('username');
-        }, { auto_login: false,
-              allow_registration: true,
-            }));
+            done();
+            });
+        }));
+
+        it("will set form_type to xform and submit it as xform",
+            mock.initConverseWithPromises(
+                null, ['connectionInitialized', 'chatBoxesInitialized'],
+                { auto_login: false,
+                  allow_registration: true },
+                function (done, _converse) {
+
+            test_utils.waitUntil(function () {
+                    return _.get(_converse.chatboxviews.get('controlbox'), 'registerpanel');
+                }, 300)
+            .then(function () {
 
-        it("will set form_type to xform and submit it as xform", mock.initConverse(function (_converse) {
             var cbview = _converse.chatboxviews.get('controlbox');
             cbview.$('#controlbox-tabs').find('li').last().find('a').click(); // Click the Register tab
             var registerview = _converse.chatboxviews.get('controlbox').registerpanel;
@@ -208,8 +273,8 @@
             expect($stanza.children('query').children().length).toBe(1);
             expect($stanza.children('query').children().children().length).toBe(3);
             expect($stanza.children('query').children().children()[0].tagName).toBe('field');
-        }, { auto_login: false,
-              allow_registration: true,
-            }));
+            done();
+            });
+        }));
     });
 }));

+ 12 - 5
src/converse-chatboxes.js

@@ -50,7 +50,10 @@
              */
             const { _converse } = this;
 
-            _converse.api.promises.add('chatBoxesFetched');
+            _converse.api.promises.add([
+                'chatBoxesFetched',
+                'chatBoxesInitialized'
+            ]);
 
             _converse.ChatBoxes = Backbone.Collection.extend({
                 comparator: 'time_opened',
@@ -312,15 +315,20 @@
                 }
             });
 
-            _converse.chatboxes = new _converse.ChatBoxes();
-            _converse.chatboxviews = new _converse.ChatBoxViews({
-                'model': this.chatboxes
+            // BEGIN: Event handlers
+            _converse.api.listen.on('pluginsInitialized', () => {
+                _converse.chatboxes = new _converse.ChatBoxes();
+                _converse.chatboxviews = new _converse.ChatBoxViews({
+                    'model': _converse.chatboxes
+                });
+                _converse.emit('chatBoxesInitialized');
             });
 
             _converse.api.listen.on('beforeTearDown', () => {
                 this.chatboxes.remove(); // Don't call off(), events won't get re-registered upon reconnect.
                 delete this.chatboxes.browserStorage;
             });
+            // END: Event handlers
 
             _converse.getViewForChatBox = function (chatbox) {
                 if (!chatbox) { return; }
@@ -331,7 +339,6 @@
             _.extend(_converse.api, {
                 'chats': {
                     'open' (jids, attrs) {
-                        debugger;
                         if (_.isUndefined(jids)) {
                             _converse.log("chats.open: You need to provide at least one JID", Strophe.LogLevel.ERROR);
                             return null;

+ 20 - 23
src/converse-controlbox.js

@@ -48,7 +48,7 @@
 
     const USERS_PANEL_ID = 'users';
     const CHATBOX_TYPE = 'chatbox';
-    const { Strophe, Backbone, utils, _, moment } = converse.env;
+    const { Strophe, Backbone, Promise, utils, _, moment } = converse.env;
 
 
     converse.plugins.add('converse-controlbox', {
@@ -60,18 +60,6 @@
             //
             // New functions which don't exist yet can also be added.
 
-            initChatBoxes () {
-                this.__super__.initChatBoxes.apply(this, arguments);
-                this.controlboxtoggle = new this.ControlBoxToggle();
-            },
-
-            initConnection () {
-                this.__super__.initConnection.apply(this, arguments);
-                if (this.connection) {
-                    this.addControlBox();
-                }
-            },
-
             _tearDown () {
                 this.__super__._tearDown.apply(this, arguments);
                 if (this.rosterview) {
@@ -215,6 +203,7 @@
                 },
 
                 initialize () {
+                    _converse.controlboxtoggle = new _converse.ControlBoxToggle();
                     this.$el.insertAfter(_converse.controlboxtoggle.$el);
                     this.model.on('change:connected', this.onConnected, this);
                     this.model.on('destroy', this.hide, this);
@@ -222,9 +211,9 @@
                     this.model.on('show', this.show, this);
                     this.model.on('change:closed', this.ensureClosedState, this);
                     this.render();
-                    if (this.model.get('connected')) {
-                        this.insertRoster();
-                    }
+                    _converse.api.waitUntil('rosterViewInitialized')
+                        .then(this.insertRoster.bind(this))
+                        .catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
                 },
 
                 render () {
@@ -256,7 +245,10 @@
 
                 onConnected () {
                     if (this.model.get('connected')) {
-                        this.render().insertRoster();
+                        this.render();
+                        _converse.api.waitUntil('rosterViewInitialized')
+                            .then(this.insertRoster.bind(this))
+                            .catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
                         this.model.save();
                     }
                 },
@@ -732,7 +724,7 @@
                 },
 
                 initialize () {
-                    _converse.chatboxviews.$el.prepend(this.render());
+                    _converse.chatboxviews.$el.prepend(this.render().el);
                     this.updateOnlineCount();
                     const that = this;
                     _converse.api.waitUntil('initialized').then(() => {
@@ -748,11 +740,10 @@
                     // the ControlBox or the Toggle must be shown. This prevents
                     // artifacts (i.e. on page load the toggle is shown only to then
                     // seconds later be hidden in favor of the control box).
-                    return this.$el.html(
-                        tpl_controlbox_toggle({
-                            'label_toggle': __('Toggle chat')
-                        })
-                    );
+                    this.el.innerHTML = tpl_controlbox_toggle({
+                        'label_toggle': __('Toggle chat')
+                    })
+                    return this;
                 },
 
                 updateOnlineCount: _.debounce(function () {
@@ -802,6 +793,12 @@
                 }
             });
 
+            Promise.all([
+                _converse.api.waitUntil('connectionInitialized'),
+                _converse.api.waitUntil('chatBoxesInitialized')
+            ]).then(_converse.addControlBox)
+              .catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
+
             const disconnect =  function () {
                 /* Upon disconnection, set connected to `false`, so that if
                  * we reconnect,

+ 27 - 24
src/converse-core.js

@@ -152,6 +152,7 @@
     const PROMISES = [
         'initialized',
         'cachedRoster',
+        'connectionInitialized',
         'pluginsInitialized',
         'roster',
         'rosterContactsFetched',
@@ -575,11 +576,11 @@
             });
 
         this.initSession = function () {
-            this.session = new Backbone.Model();
+            _converse.session = new Backbone.Model();
             const id = b64_sha1('converse.bosh-session');
-            this.session.id = id; // Appears to be necessary for backbone.browserStorage
-            this.session.browserStorage = new Backbone.BrowserStorage[_converse.storage](id);
-            this.session.fetch();
+            _converse.session.id = id; // Appears to be necessary for backbone.browserStorage
+            _converse.session.browserStorage = new Backbone.BrowserStorage[_converse.storage](id);
+            _converse.session.fetch();
         };
 
         this.clearSession = function () {
@@ -1778,22 +1779,22 @@
         };
 
         this.initConnection = function () {
-            if (this.connection) {
-                return;
-            }
-            if (!this.bosh_service_url && ! this.websocket_url) {
-                throw new Error("initConnection: you must supply a value for either the bosh_service_url or websocket_url or both.");
-            }
-            if (('WebSocket' in window || 'MozWebSocket' in window) && this.websocket_url) {
-                this.connection = new Strophe.Connection(this.websocket_url, this.connection_options);
-            } else if (this.bosh_service_url) {
-                this.connection = new Strophe.Connection(
-                    this.bosh_service_url,
-                    _.assignIn(this.connection_options, {'keepalive': this.keepalive})
-                );
-            } else {
-                throw new Error("initConnection: this browser does not support websockets and bosh_service_url wasn't specified.");
+            if (!this.connection) {
+                if (!this.bosh_service_url && ! this.websocket_url) {
+                    throw new Error("initConnection: you must supply a value for either the bosh_service_url or websocket_url or both.");
+                }
+                if (('WebSocket' in window || 'MozWebSocket' in window) && this.websocket_url) {
+                    this.connection = new Strophe.Connection(this.websocket_url, this.connection_options);
+                } else if (this.bosh_service_url) {
+                    this.connection = new Strophe.Connection(
+                        this.bosh_service_url,
+                        _.assignIn(this.connection_options, {'keepalive': this.keepalive})
+                    );
+                } else {
+                    throw new Error("initConnection: this browser does not support websockets and bosh_service_url wasn't specified.");
+                }
             }
+            _converse.emit('connectionInitialized');
         };
 
         this._tearDown = function () {
@@ -1801,11 +1802,13 @@
              * connection.
              */
             _converse.emit('beforeTearDown');
-            this.unregisterPresenceHandler();
-            if (this.roster) {
-                this.roster.off().reset(); // Removes roster contacts
+            _converse.unregisterPresenceHandler();
+            if (_converse.roster) {
+                _converse.roster.off().reset(); // Removes roster contacts
+            }
+            if (!_.isUndefined(_converse.session)) {
+                _converse.session.destroy();
             }
-            this.session.destroy();
             window.removeEventListener('click', _converse.onUserActivity);
             window.removeEventListener('focus', _converse.onUserActivity);
             window.removeEventListener('keypress', _converse.onUserActivity);
@@ -1813,7 +1816,7 @@
             window.removeEventListener(unloadevent, _converse.onUserActivity);
             window.clearInterval(_converse.everySecondTrigger);
             _converse.emit('afterTearDown');
-            return this;
+            return _converse;
         };
 
         this.initPlugins = function () {

+ 12 - 13
src/converse-minimize.js

@@ -27,7 +27,7 @@
     ) {
     "use strict";
 
-    const { _ , utils, Backbone, b64_sha1, moment } = converse.env;
+    const { _ , utils, Backbone, Promise, Strophe, b64_sha1, moment } = converse.env;
 
     converse.plugins.add('converse-minimize', {
         overrides: {
@@ -37,15 +37,6 @@
             //
             // New functions which don't exist yet can also be added.
 
-            initChatBoxes () {
-                const { _converse } = this.__super__;
-                const result = this.__super__.initChatBoxes.apply(this, arguments);
-                _converse.minimized_chats = new _converse.MinimizedChats({
-                    model: _converse.chatboxes
-                });
-                return result;
-            },
-
             registerGlobalEventHandlers () {
                 const { _converse } = this.__super__;
                 $(window).on("resize", _.debounce(function (ev) {
@@ -492,7 +483,16 @@
                 }
             });
 
-            const renderMinimizeButton = function (view) {
+            Promise.all([
+                _converse.api.waitUntil('connectionInitialized'),
+                _converse.api.waitUntil('chatBoxesInitialized')
+            ]).then(() => {
+                _converse.minimized_chats = new _converse.MinimizedChats({
+                    model: _converse.chatboxes
+                });
+            }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
+
+            _converse.on('chatBoxOpened', function renderMinimizeButton (view) {
                 // Inserts a "minimize" button in the chatview's header
                 const $el = view.$el.find('.toggle-chatbox-button');
                 const $new_el = tpl_chatbox_minimize(
@@ -503,8 +503,7 @@
                 } else {
                     view.$el.find('.close-chatbox-button').after($new_el);
                 }
-            };
-            _converse.on('chatBoxOpened', renderMinimizeButton);
+            });
 
             _converse.on('controlBoxOpened', function (chatbox) {
                 // Wrapped in anon method because at scan time, chatboxviews

+ 2 - 0
src/converse-rosterview.js

@@ -76,6 +76,7 @@
                 allow_contact_removal: true,
                 show_toolbar: true,
             });
+            _converse.api.promises.add('rosterViewInitialized');
 
             const STATUSES = {
                 'dnd': __('This contact is busy'),
@@ -950,6 +951,7 @@
                     'model': _converse.rostergroups
                 });
                 _converse.rosterview.render();
+                _converse.emit('rosterViewInitialized');
             };
             _converse.api.listen.on('rosterInitialized', initRoster);
             _converse.api.listen.on('rosterReadyAfterReconnection', initRoster);