JC Brand 6 rokov pred
rodič
commit
3fe6efc2cf
5 zmenil súbory, kde vykonal 125 pridanie a 43 odobranie
  1. 62 28
      dist/converse.js
  2. 8 4
      spec/chatbox.js
  3. 49 10
      spec/messages.js
  4. 2 1
      spec/notification.js
  5. 4 0
      spec/spoilers.js

+ 62 - 28
dist/converse.js

@@ -62023,23 +62023,6 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
         return attrs;
       },
 
-      async createMessage(stanza, original_stanza) {
-        const msgid = stanza.getAttribute('id'),
-              message = msgid && this.messages.findWhere({
-          msgid
-        });
-
-        if (!message) {
-          // Only create the message when we're sure it's not a duplicate
-          const attrs = await this.getMessageAttributesFromStanza(stanza, original_stanza);
-
-          if (attrs['chat_state'] || !u.isEmptyMessage(attrs)) {
-            const msg = this.messages.create(attrs);
-            this.incrementUnreadMsgCounter(msg);
-          }
-        }
-      },
-
       isHidden() {
         /* Returns a boolean to indicate whether a newly received
          * message will be visible to the user or not.
@@ -62249,6 +62232,13 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
           contact_jid = Strophe.getBareJidFromJid(to_jid);
         } else {
           contact_jid = from_bare_jid;
+          await _converse.api.waitUntil('rosterContactsFetched');
+
+          const roster_item = _converse.roster.get(contact_jid);
+
+          if (_.isUndefined(roster_item) && !_converse.allow_non_roster_messaging) {
+            return;
+          }
         } // Get chat box, but only create when the message has something to show to the user
 
 
@@ -62259,7 +62249,12 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
               chatbox = this.getChatBox(contact_jid, chatbox_attrs, has_body);
 
         if (chatbox && !chatbox.handleMessageCorrection(stanza) && !chatbox.handleReceipt(stanza, from_jid, is_carbon, is_me) && !chatbox.handleChatMarker(stanza, from_jid, is_carbon)) {
-          await chatbox.createMessage(stanza, original_stanza);
+          const attrs = await chatbox.getMessageAttributesFromStanza(stanza, original_stanza);
+
+          if (attrs['chat_state'] || !u.isEmptyMessage(attrs)) {
+            const msg = chatbox.messages.create(attrs);
+            chatbox.incrementUnreadMsgCounter(msg);
+          }
         }
 
         _converse.emit('message', {
@@ -66997,7 +66992,41 @@ _converse_core__WEBPACK_IMPORTED_MODULE_6__["default"].plugins.add('converse-muc
                      acknowledged[xmlns="${Strophe.NS.MARKERS}"]`, stanza).length > 0;
       },
 
+      reflectionHandled(stanza) {
+        /* Handle a MUC reflected message and return true if so.
+         *
+         * Parameters:
+         *  (XMLElement) stanza: The message stanza
+         */
+        const from = stanza.getAttribute('from');
+        const own_message = Strophe.getResourceFromJid(from) == this.get('nick');
+
+        if (own_message) {
+          const msgid = stanza.getAttribute('id'),
+                jid = stanza.getAttribute('from'); // TODO: use stanza-id?
+
+          if (msgid) {
+            const msg = this.messages.findWhere({
+              'msgid': msgid,
+              'from': jid
+            });
+
+            if (msg && msg.get('sender') === 'me' && !msg.get('received')) {
+              msg.save({
+                'received': moment().format()
+              });
+              return true;
+            }
+          }
+        }
+      },
+
       subjectChangeHandled(attrs) {
+        /* Handle a subject change and return `true` if so.
+         *
+         * Parameters:
+         *  (Object) attrs: The message attributes
+         */
         if (attrs.subject && !attrs.thread && !attrs.message) {
           // https://xmpp.org/extensions/xep-0045.html#subject-mod
           // -----------------------------------------------------
@@ -67016,6 +67045,18 @@ _converse_core__WEBPACK_IMPORTED_MODULE_6__["default"].plugins.add('converse-muc
         return false;
       },
 
+      ignorableCSN(attrs) {
+        /* Is this a chat state notification that can be ignored,
+         * because it's old or because it's from us.
+         *
+         * Parameters:
+         *  (Object) attrs: The message attributes
+         */
+        const is_csn = _utils_form__WEBPACK_IMPORTED_MODULE_7__["default"].isOnlyChatStateNotification(attrs),
+              own_message = Strophe.getResourceFromJid(attrs.from) == this.get('nick');
+        return is_csn && (attrs.is_delayed || own_message);
+      },
+
       async onMessage(stanza) {
         /* Handler for all MUC messages sent to this groupchat.
          *
@@ -67040,16 +67081,9 @@ _converse_core__WEBPACK_IMPORTED_MODULE_6__["default"].plugins.add('converse-muc
           return;
         }
 
-        if (!this.handleMessageCorrection(stanza) && !this.isReceipt(stanza) && !this.isChatMarker(stanza) && !this.subjectChangeHandled(attrs)) {
-          const is_csn = _utils_form__WEBPACK_IMPORTED_MODULE_7__["default"].isOnlyChatStateNotification(attrs),
-                own_message = Strophe.getResourceFromJid(attrs.from) == this.get('nick');
-
-          if (is_csn && (attrs.is_delayed || own_message)) {
-            // No need showing delayed or our own CSN messages
-            return;
-          }
-
-          const msg = await this.createMessage(stanza, original_stanza);
+        if (!this.handleMessageCorrection(stanza) && !this.isReceipt(stanza) && !this.isChatMarker(stanza) && !this.reflectionHandled(stanza) && !this.subjectChangeHandled(attrs) && !this.ignorableCSN(attrs) && (attrs['chat_state'] || !_utils_form__WEBPACK_IMPORTED_MODULE_7__["default"].isEmptyMessage(attrs))) {
+          const msg = this.messages.create(attrs);
+          this.incrementUnreadMsgCounter(msg);
 
           if (forwarded && msg && msg.get('sender') === 'me') {
             msg.save({

+ 8 - 4
spec/chatbox.js

@@ -144,6 +144,7 @@
                 null, ['rosterGroupsFetched'], {'allow_non_roster_messaging': true},
                 async function (done, _converse) {
 
+                _converse.emit('rosterContactsFetched');
                 const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
                 const stanza = u.toStanza(`
                     <message from="${sender_jid}"
@@ -154,6 +155,7 @@
 
                 const message_promise = new Promise(resolve => _converse.api.listen.on('message', resolve));
                 _converse.connection._dataRecv(test_utils.createRequest(stanza));
+                await test_utils.waitUntil(() => _converse.api.chats.get().length === 2);
                 await test_utils.waitUntil(() => message_promise);
                 expect(_converse.chatboxviews.keys().length).toBe(2);
                 done();
@@ -568,6 +570,7 @@
                         async function (done, _converse) {
 
                     test_utils.createContacts(_converse, 'current');
+                    _converse.emit('rosterContactsFetched');
                     test_utils.openControlBox();
 
                     spyOn(_converse, 'emit');
@@ -581,6 +584,7 @@
                         }).c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree();
                     await _converse.chatboxes.onMessage(msg);
                     expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object));
+                    expect(_converse.api.chats.get().length).toBe(1);
                     done();
                 }));
 
@@ -1054,6 +1058,7 @@
                             async function (done, _converse) {
 
                         test_utils.createContacts(_converse, 'current', 3);
+                        _converse.emit('rosterContactsFetched');
                         test_utils.openControlBox();
 
                         spyOn(_converse, 'emit');
@@ -1209,6 +1214,7 @@
                     async function (done, _converse) {
 
                 test_utils.createContacts(_converse, 'current');
+                _converse.emit('rosterContactsFetched');
                 // initial state
                 expect(_converse.msg_counter).toBe(0);
                 const message = 'This message will always increment the message counter from zero',
@@ -1228,9 +1234,8 @@
                 // leave converse-chat page
                 _converse.windowState = 'hidden';
                 _converse.chatboxes.onMessage(msgFactory());
-                await test_utils.waitUntil(() => _converse.api.chats.get().length)
+                await test_utils.waitUntil(() => _converse.api.chats.get().length === 2)
                 let view = _converse.chatboxviews.get(sender_jid);
-                await new Promise((resolve, reject) => view.once('messageInserted', resolve));
                 expect(_converse.msg_counter).toBe(1);
 
                 // come back to converse-chat page
@@ -1244,9 +1249,8 @@
 
                 // check that msg_counter is incremented from zero again
                 _converse.chatboxes.onMessage(msgFactory());
-                await test_utils.waitUntil(() => _converse.api.chats.get().length)
+                await test_utils.waitUntil(() => _converse.api.chats.get().length === 2)
                 view = _converse.chatboxviews.get(sender_jid);
-                await new Promise((resolve, reject) => view.once('messageInserted', resolve));
                 expect(u.isVisible(view.el)).toBeTruthy();
                 expect(_converse.msg_counter).toBe(1);
                 done();

+ 49 - 10
spec/messages.js

@@ -538,6 +538,7 @@
             expect(msg_obj.get('is_delayed')).toEqual(false);
             // Now check that the message appears inside the chatbox in the DOM
             const chat_content = view.el.querySelector('.chat-content');
+            await new Promise((resolve, reject) => view.once('messageInserted', resolve));
             expect(chat_content.querySelector('.chat-msg .chat-msg__text').textContent).toEqual(msgtext);
             expect(chat_content.querySelector('.chat-msg__time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy();
             await test_utils.waitUntil(() => chatbox.vcard.get('fullname') === 'Candice van der Knijff')
@@ -552,6 +553,7 @@
 
             await test_utils.waitUntilDiscoConfirmed(_converse, 'localhost', [], ['vcard-temp']);
             test_utils.createContacts(_converse, 'current');
+            _converse.emit('rosterContactsFetched');
             test_utils.openControlBox();
 
             // Send a message from a different resource
@@ -579,6 +581,7 @@
             const view = _converse.chatboxviews.get(recipient_jid);
             expect(chatbox).toBeDefined();
             expect(view).toBeDefined();
+            await new Promise(resolve => view.once('messageInserted', resolve));
             // Check that the message was received and check the message parameters
             expect(chatbox.messages.length).toEqual(1);
             const msg_obj = chatbox.messages.models[0];
@@ -1030,6 +1033,7 @@
                 async function (done, _converse) {
 
             test_utils.createContacts(_converse, 'current');
+            _converse.emit('rosterContactsFetched');
             test_utils.openControlBox();
 
             let message, msg;
@@ -1050,6 +1054,7 @@
                     'id': (new Date()).getTime()
                 }).c('body').t('A message').up()
                 .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
+            await new Promise(resolve => _converse.on('chatBoxOpened', resolve));
             const view = await _converse.chatboxviews.get(sender_jid);
             await new Promise((resolve, reject) => view.once('messageInserted', resolve));
 
@@ -1195,6 +1200,7 @@
                 null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
                 async function (done, _converse) {
             test_utils.createContacts(_converse, 'current', 1);
+            _converse.emit('rosterContactsFetched');
             const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
             const msg_id = u.getUniqueId();
             const sent_stanzas = [];
@@ -1209,7 +1215,7 @@
                 }).c('body').t('Message!').up()
                 .c('request', {'xmlns': Strophe.NS.RECEIPTS}).tree();
             await _converse.chatboxes.onMessage(msg);
-            const receipt = sizzle(`received[xmlns="${Strophe.NS.RECEIPTS}"]`, sent_stanzas[0].tree()).pop();
+            const receipt = sizzle(`received[xmlns="${Strophe.NS.RECEIPTS}"]`, sent_stanzas[1].tree()).pop();
             expect(Strophe.serialize(receipt)).toBe(`<received id="${msg_id}" xmlns="${Strophe.NS.RECEIPTS}"/>`);
             done();
         }));
@@ -1341,6 +1347,7 @@
                     async function (done, _converse) {
 
                 test_utils.createContacts(_converse, 'current');
+                _converse.emit('rosterContactsFetched');
                 test_utils.openControlBox();
                 await test_utils.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length, 300);
                 spyOn(_converse, 'emit');
@@ -1357,12 +1364,11 @@
                     }).c('body').t(message).up()
                     .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree()
                 );
-                await test_utils.waitUntil(() => _converse.api.chats.get().length);
+                await test_utils.waitUntil(() => _converse.api.chats.get().length === 2);
                 const chatbox = _converse.chatboxes.get(sender_jid);
                 expect(chatbox).toBeDefined();
                 const view = _converse.chatboxviews.get(sender_jid);
                 expect(view).toBeDefined();
-                await new Promise((resolve, reject) => view.once('messageInserted', resolve));
 
                 expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object));
                 // Check that the message was received and check the message parameters
@@ -1449,6 +1455,7 @@
                         null, ['rosterGroupsFetched'], {},
                         async function (done, _converse) {
 
+                    _converse.emit('rosterContactsFetched');
                     _converse.allow_non_roster_messaging = true;
                     spyOn(_converse, 'emit').and.callThrough();
 
@@ -1485,6 +1492,7 @@
                     expect(chatbox).toBeDefined();
                     expect(view).toBeDefined();
                     expect(chatbox.get('fullname') === sender_jid);
+                    await new Promise(resolve => view.once('messageInserted', resolve));
 
                     await test_utils.waitUntil(() => view.el.querySelector('.chat-msg__author').textContent.trim() === 'Max Frankfurter');
                     let author_el = view.el.querySelector('.chat-msg__author');
@@ -1507,6 +1515,7 @@
                         async function (done, _converse) {
 
                     _converse.allow_non_roster_messaging = false;
+                    _converse.emit('rosterContactsFetched');
 
                     spyOn(_converse, 'emit');
                     const message = 'This is a received message from someone not on the roster';
@@ -1526,15 +1535,15 @@
                     expect(chatbox).not.toBeDefined();
                     // onMessage is a handler for received XMPP messages
                     await _converse.chatboxes.onMessage(msg);
+                    expect(_converse.api.chats.get().length).toBe(1);
+                    let view = _converse.chatboxviews.get(sender_jid);
+                    expect(view).not.toBeDefined();
 
-                    await test_utils.waitUntil(() => _converse.api.chats.get().length)
-                    const view = _converse.chatboxviews.get(sender_jid);
-
-                    expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object));
                     // onMessage is a handler for received XMPP messages
-                    _converse.allow_non_roster_messaging =true;
+                    _converse.allow_non_roster_messaging = true;
                     await _converse.chatboxes.onMessage(msg);
-                    await test_utils.waitUntil(() => view.model.messages.length);
+                    view = _converse.chatboxviews.get(sender_jid);
+                    await new Promise((resolve, reject) => view.once('messageInserted', resolve));
                     expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object));
                     // Check that the chatbox and its view now exist
                     chatbox = _converse.chatboxes.get(sender_jid);
@@ -2109,7 +2118,6 @@
                 null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
                 async function (done, _converse) {
 
-            test_utils.createContacts(_converse, 'current');
             await test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy');
             const view = _converse.chatboxviews.get('lounge@localhost');
             if (!view.el.querySelectorAll('.chat-area').length) { view.renderChatArea(); }
@@ -2128,6 +2136,37 @@
         }));
 
 
+        it("can not be expected to have a unique id attribute",
+            mock.initConverse(
+                null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
+                async function (done, _converse) {
+
+            await test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy');
+            const view = _converse.chatboxviews.get('lounge@localhost');
+            if (!view.el.querySelectorAll('.chat-area').length) { view.renderChatArea(); }
+            const id = u.getUniqueId();
+            let msg = $msg({
+                    from: 'lounge@localhost/some1',
+                    id: id,
+                    to: 'dummy@localhost',
+                    type: 'groupchat'
+                }).c('body').t('First message').tree();
+            await view.model.onMessage(msg);
+            await new Promise((resolve, reject) => view.once('messageInserted', resolve));
+            expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
+
+            msg = $msg({
+                    from: 'lounge@localhost/some2',
+                    id: id,
+                    to: 'dummy@localhost',
+                    type: 'groupchat'
+                }).c('body').t('Another message').tree();
+            await view.model.onMessage(msg);
+            await new Promise((resolve, reject) => view.once('messageInserted', resolve));
+            expect(view.el.querySelectorAll('.chat-msg').length).toBe(2);
+            done();
+        }));
+
         it("keeps track whether you are the sender or not",
             mock.initConverse(
                 null, ['rosterGroupsFetched'], {},

+ 2 - 1
spec/notification.js

@@ -72,7 +72,8 @@
                                 to: 'dummy@localhost',
                                 type: 'groupchat'
                             }).c('body').t(message).tree();
-                        await _converse.chatboxes.onMessage(msg); // This will emit 'message'
+
+                        _converse.connection._dataRecv(test_utils.createRequest(msg));
                         await new Promise((resolve, reject) => view.once('messageInserted', resolve));
                         expect(_converse.areDesktopNotificationsEnabled).toHaveBeenCalled();
                         expect(_converse.showMessageNotification).toHaveBeenCalled();

+ 4 - 0
spec/spoilers.js

@@ -15,6 +15,7 @@
                 async (done, _converse) => {
 
             test_utils.createContacts(_converse, 'current');
+            _converse.emit('rosterContactsFetched');
             const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
 
             /* <message to='romeo@montague.net/orchard' from='juliet@capulet.net/balcony' id='spoiler2'>
@@ -36,6 +37,7 @@
                 .tree();
             _converse.chatboxes.onMessage(msg);
 
+            await test_utils.waitUntil(() => _converse.api.chats.get().length === 2);
             const view = _converse.chatboxviews.get(sender_jid);
             await test_utils.waitUntil(() => view.model.vcard.get('fullname') === 'Max Frankfurter')
             expect(view.el.querySelector('.chat-msg__author').textContent.trim()).toBe('Max Frankfurter');
@@ -52,6 +54,7 @@
                 async (done, _converse) => {
 
             test_utils.createContacts(_converse, 'current');
+            _converse.emit('rosterContactsFetched');
             const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
             /* <message to='romeo@montague.net/orchard' from='juliet@capulet.net/balcony' id='spoiler2'>
              *      <body>And at the end of the story, both of them die! It is so tragic!</body>
@@ -69,6 +72,7 @@
                       'xmlns': 'urn:xmpp:spoiler:0',
                     }).tree();
             _converse.chatboxes.onMessage(msg);
+            await test_utils.waitUntil(() => _converse.api.chats.get().length === 2);
             const view = _converse.chatboxviews.get(sender_jid);
             await test_utils.waitUntil(() => view.model.vcard.get('fullname') === 'Max Frankfurter')
             expect(_.includes(view.el.querySelector('.chat-msg__author').textContent, 'Max Frankfurter')).toBeTruthy();