Prechádzať zdrojové kódy

Reduce join/leave clutter by removing subsequent ones

Previously we checked only if the last message was a join message from
the same person.

Now instead we check the last n messages that are join or leave
notifications.
JC Brand 6 rokov pred
rodič
commit
71cc98d6f6
4 zmenil súbory, kde vykonal 86 pridanie a 40 odobranie
  1. 1 0
      CHANGES.md
  2. 27 14
      dist/converse.js
  3. 33 5
      spec/chatroom.js
  4. 25 21
      src/converse-muc-views.js

+ 1 - 0
CHANGES.md

@@ -2,6 +2,7 @@
 
 
 ## 4.0.3 (Unreleased)
 ## 4.0.3 (Unreleased)
 
 
+- Reduce join/leave clutter by removing subsequent ones (without text messages in between)
 - Bugfix. Handler not triggered when submitting MUC password form 2nd time
 - Bugfix. Handler not triggered when submitting MUC password form 2nd time
 - Bugfix. MUC features weren't being refreshed when saving the config form
 - Bugfix. MUC features weren't being refreshed when saving the config form
 - #1063 URLs in the topic / subject are not clickable
 - #1063 URLs in the topic / subject are not clickable

+ 27 - 14
dist/converse.js

@@ -69771,6 +69771,22 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
           this.scrollDown();
           this.scrollDown();
         },
         },
 
 
+        getImmediateJoinNotification(el, nick) {
+          while (!_.isNil(el)) {
+            const data = _.get(el, 'dataset', {});
+
+            if (!_.includes(_.get(el, 'classList', []), 'chat-info')) {
+              return;
+            }
+
+            if (moment(el.getAttribute('data-isodate')).isSame(new Date(), "day") && (data.join === `"${nick}"` || data.leavejoin === `"${nick}"`)) {
+              return el;
+            }
+
+            el = el.previousElementSibling;
+          }
+        },
+
         showLeaveNotification(occupant) {
         showLeaveNotification(occupant) {
           if (_.includes(occupant.get('states'), '303') || _.includes(occupant.get('states'), '307')) {
           if (_.includes(occupant.get('states'), '303') || _.includes(occupant.get('states'), '307')) {
             return;
             return;
@@ -69778,10 +69794,10 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
 
 
           const nick = occupant.get('nick'),
           const nick = occupant.get('nick'),
                 stat = occupant.get('status'),
                 stat = occupant.get('status'),
-                last_el = this.content.lastElementChild,
-                data = _.get(last_el, 'dataset', {});
+                last_join_el = this.getImmediateJoinNotification(this.content.lastElementChild, nick),
+                data = _.get(last_join_el, 'dataset', {});
 
 
-          if (last_el && _.includes(_.get(last_el, 'classList', []), 'chat-info') && moment(last_el.getAttribute('data-isodate')).isSame(new Date(), "day") && (data.join === `"${nick}"` || data.leavejoin === `"${nick}"`)) {
+          if (last_join_el) {
             let message;
             let message;
 
 
             if (data.join === `"${nick}"`) {
             if (data.join === `"${nick}"`) {
@@ -69791,13 +69807,15 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
                 message = __('%1$s has entered and left the groupchat. "%2$s"', nick, stat);
                 message = __('%1$s has entered and left the groupchat. "%2$s"', nick, stat);
               }
               }
 
 
-              last_el.outerHTML = tpl_info({
+              let el = this.content.lastElementChild;
+              el.insertAdjacentElement('afterend', last_join_el);
+              last_join_el.outerHTML = tpl_info({
                 'data': `data-joinleave="${nick}"`,
                 'data': `data-joinleave="${nick}"`,
                 'isodate': moment().format(),
                 'isodate': moment().format(),
                 'extra_classes': 'chat-event',
                 'extra_classes': 'chat-event',
                 'message': message
                 'message': message
               });
               });
-              const el = this.content.lastElementChild;
+              el = this.content.lastElementChild;
               setTimeout(() => u.addClass('fade-out', el), 5000);
               setTimeout(() => u.addClass('fade-out', el), 5000);
               setTimeout(() => el.parentElement && el.parentElement.removeChild(el), 5250);
               setTimeout(() => el.parentElement && el.parentElement.removeChild(el), 5250);
             } else if (data.leavejoin === `"${nick}"`) {
             } else if (data.leavejoin === `"${nick}"`) {
@@ -69807,7 +69825,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
                 message = __('%1$s has left the groupchat. "%2$s"', nick, stat);
                 message = __('%1$s has left the groupchat. "%2$s"', nick, stat);
               }
               }
 
 
-              last_el.outerHTML = tpl_info({
+              last_join_el.outerHTML = tpl_info({
                 'data': `data-leave="${nick}"`,
                 'data': `data-leave="${nick}"`,
                 'isodate': moment().format(),
                 'isodate': moment().format(),
                 'extra_classes': 'chat-event',
                 'extra_classes': 'chat-event',
@@ -69829,14 +69847,9 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
               'extra_classes': 'chat-event',
               'extra_classes': 'chat-event',
               'data': `data-leave="${nick}"`
               'data': `data-leave="${nick}"`
             };
             };
-
-            if (last_el && _.includes(_.get(last_el, 'classList', []), 'chat-info') && _.get(last_el, 'dataset', {}).leavejoin === `"${nick}"`) {
-              last_el.outerHTML = tpl_info(data);
-            } else {
-              const el = u.stringToElement(tpl_info(data));
-              this.content.insertAdjacentElement('beforeend', el);
-              this.insertDayIndicator(el);
-            }
+            const el = u.stringToElement(tpl_info(data));
+            this.content.insertAdjacentElement('beforeend', el);
+            this.insertDayIndicator(el);
           }
           }
 
 
           this.scrollDown();
           this.scrollDown();

+ 33 - 5
spec/chatroom.js

@@ -422,7 +422,8 @@
                 test_utils.openChatRoom(_converse, "coven", 'chat.shakespeare.lit', 'some1')
                 test_utils.openChatRoom(_converse, "coven", 'chat.shakespeare.lit', 'some1')
                 .then(() => {
                 .then(() => {
                     const view = _converse.chatboxviews.get('coven@chat.shakespeare.lit');
                     const view = _converse.chatboxviews.get('coven@chat.shakespeare.lit');
-                    const $chat_content = $(view.el).find('.chat-content');
+                    const chat_content = view.el.querySelector('.chat-content');
+                    const $chat_content = $(chat_content);
                     /* We don't show join/leave messages for existing occupants. We
                     /* We don't show join/leave messages for existing occupants. We
                      * know about them because we receive their presences before we
                      * know about them because we receive their presences before we
                      * receive our own.
                      * receive our own.
@@ -474,6 +475,15 @@
                     expect($chat_content[0].querySelectorAll('div.chat-info').length).toBe(2);
                     expect($chat_content[0].querySelectorAll('div.chat-info').length).toBe(2);
                     expect($chat_content.find('div.chat-info:last').html()).toBe("newguy has entered the groupchat");
                     expect($chat_content.find('div.chat-info:last').html()).toBe("newguy has entered the groupchat");
 
 
+                    const msg = $msg({
+                        'from': 'coven@chat.shakespeare.lit/some1',
+                        'id': (new Date()).getTime(),
+                        'to': 'dummy@localhost',
+                        'type': 'groupchat'
+                    }).c('body').t('hello world').tree();
+                    _converse.connection._dataRecv(test_utils.createRequest(msg));
+
+
                     // Add another entrant, otherwise the above message will be
                     // Add another entrant, otherwise the above message will be
                     // collapsed if "newguy" leaves immediately again
                     // collapsed if "newguy" leaves immediately again
                     presence = $pres({
                     presence = $pres({
@@ -563,9 +573,9 @@
                             });
                             });
                     _converse.connection._dataRecv(test_utils.createRequest(presence));
                     _converse.connection._dataRecv(test_utils.createRequest(presence));
                     expect($chat_content.find('div.chat-info').length).toBe(4);
                     expect($chat_content.find('div.chat-info').length).toBe(4);
-                    $msg_el = $chat_content.find('div.chat-info:last');
-                    expect($msg_el.html()).toBe('newguy has left the groupchat');
-                    expect($msg_el.data('leave')).toBe('"newguy"');
+                    const msg_el = sizzle('div.chat-info', chat_content).pop();
+                    expect(msg_el.textContent).toBe('newguy has left the groupchat');
+                    expect(msg_el.getAttribute('data-leave')).toBe('"newguy"');
 
 
                     presence = $pres({
                     presence = $pres({
                             to: 'dummy@localhost/_converse.js-29092160',
                             to: 'dummy@localhost/_converse.js-29092160',
@@ -648,13 +658,31 @@
                                 'role': 'none'
                                 'role': 'none'
                             });
                             });
                     _converse.connection._dataRecv(test_utils.createRequest(presence));
                     _converse.connection._dataRecv(test_utils.createRequest(presence));
-                    expect($chat_content.find('div.chat-info').length).toBe(6);
+                    expect(chat_content.querySelectorAll('div.chat-info').length).toBe(6);
                     expect($chat_content.find('div.chat-info:last').html()).toBe(
                     expect($chat_content.find('div.chat-info:last').html()).toBe(
                         'insider has entered and left the groupchat. '+
                         'insider has entered and left the groupchat. '+
                         '"Disconnected: Replaced by new connection"');
                         '"Disconnected: Replaced by new connection"');
 
 
                     expect(view.model.occupants.length).toBe(5);
                     expect(view.model.occupants.length).toBe(5);
                     expect(view.model.occupants.findWhere({'jid': 'insider@localhost'}).get('show')).toBe('offline');
                     expect(view.model.occupants.findWhere({'jid': 'insider@localhost'}).get('show')).toBe('offline');
+
+                    // New girl leaves
+                    presence = $pres({
+                            'to': 'dummy@localhost/_converse.js-29092160',
+                            'type': 'unavailable',
+                            'from': 'coven@chat.shakespeare.lit/newgirl'
+                        })
+                        .c('x', {xmlns: Strophe.NS.MUC_USER})
+                        .c('item', {
+                            'affiliation': 'none',
+                            'jid': 'newgirl@localhost/_converse.js-213098781',
+                            'role': 'none'
+                        });
+
+                    _converse.connection._dataRecv(test_utils.createRequest(presence));
+                    expect(chat_content.querySelectorAll('div.chat-info').length).toBe(6);
+                    expect(sizzle('div.chat-info:last', chat_content).pop().textContent).toBe("newgirl has entered and left the groupchat");
+                    expect(view.model.occupants.length).toBe(4);
                     done();
                     done();
                 }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
                 }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL))
             }));
             }));

+ 25 - 21
src/converse-muc-views.js

@@ -1546,20 +1546,30 @@
                     this.scrollDown();
                     this.scrollDown();
                 },
                 },
 
 
+                getImmediateJoinNotification (el, nick) {
+                    while (!_.isNil(el)) {
+                        const data = _.get(el, 'dataset', {});
+                        if (!_.includes(_.get(el, 'classList', []), 'chat-info')) {
+                            return;
+                        }
+                        if (moment(el.getAttribute('data-isodate')).isSame(new Date(), "day") &&
+                                (data.join === `"${nick}"` || data.leavejoin === `"${nick}"`)) {
+                            return el;
+                        }
+                        el = el.previousElementSibling;
+                    }
+                },
+
                 showLeaveNotification (occupant) {
                 showLeaveNotification (occupant) {
                     if (_.includes(occupant.get('states'), '303') || _.includes(occupant.get('states'), '307')) {
                     if (_.includes(occupant.get('states'), '303') || _.includes(occupant.get('states'), '307')) {
                         return;
                         return;
                     }
                     }
                     const nick = occupant.get('nick'),
                     const nick = occupant.get('nick'),
                           stat = occupant.get('status'),
                           stat = occupant.get('status'),
-                          last_el = this.content.lastElementChild,
-                          data = _.get(last_el, 'dataset', {});
-
-                    if (last_el &&
-                            _.includes(_.get(last_el, 'classList', []), 'chat-info') &&
-                            moment(last_el.getAttribute('data-isodate')).isSame(new Date(), "day") &&
-                            (data.join === `"${nick}"` || data.leavejoin === `"${nick}"`)) {
+                          last_join_el = this.getImmediateJoinNotification(this.content.lastElementChild, nick),
+                          data = _.get(last_join_el, 'dataset', {});
 
 
+                    if (last_join_el) {
                         let message;
                         let message;
                         if (data.join === `"${nick}"`) {
                         if (data.join === `"${nick}"`) {
                             if (_.isNil(stat)) {
                             if (_.isNil(stat)) {
@@ -1567,24 +1577,25 @@
                             } else {
                             } else {
                                 message = __('%1$s has entered and left the groupchat. "%2$s"', nick, stat);
                                 message = __('%1$s has entered and left the groupchat. "%2$s"', nick, stat);
                             }
                             }
-                            last_el.outerHTML =
+                            let el = this.content.lastElementChild;
+                            el.insertAdjacentElement('afterend', last_join_el);
+                            last_join_el.outerHTML =
                                 tpl_info({
                                 tpl_info({
                                     'data': `data-joinleave="${nick}"`,
                                     'data': `data-joinleave="${nick}"`,
                                     'isodate': moment().format(),
                                     'isodate': moment().format(),
                                     'extra_classes': 'chat-event',
                                     'extra_classes': 'chat-event',
                                     'message': message
                                     'message': message
                                 });
                                 });
-                            const el = this.content.lastElementChild;
+                            el = this.content.lastElementChild;
                             setTimeout(() => u.addClass('fade-out', el), 5000);
                             setTimeout(() => u.addClass('fade-out', el), 5000);
                             setTimeout(() => el.parentElement && el.parentElement.removeChild(el), 5250);
                             setTimeout(() => el.parentElement && el.parentElement.removeChild(el), 5250);
-
                         } else if (data.leavejoin === `"${nick}"`) {
                         } else if (data.leavejoin === `"${nick}"`) {
                             if (_.isNil(stat)) {
                             if (_.isNil(stat)) {
                                 message = __('%1$s has left the groupchat', nick);
                                 message = __('%1$s has left the groupchat', nick);
                             } else {
                             } else {
                                 message = __('%1$s has left the groupchat. "%2$s"', nick, stat);
                                 message = __('%1$s has left the groupchat. "%2$s"', nick, stat);
                             }
                             }
-                            last_el.outerHTML =
+                            last_join_el.outerHTML =
                                 tpl_info({
                                 tpl_info({
                                     'data': `data-leave="${nick}"`,
                                     'data': `data-leave="${nick}"`,
                                     'isodate': moment().format(),
                                     'isodate': moment().format(),
@@ -1605,16 +1616,9 @@
                             'extra_classes': 'chat-event',
                             'extra_classes': 'chat-event',
                             'data': `data-leave="${nick}"`
                             'data': `data-leave="${nick}"`
                         }
                         }
-                        if (last_el &&
-                            _.includes(_.get(last_el, 'classList', []), 'chat-info') &&
-                            _.get(last_el, 'dataset', {}).leavejoin === `"${nick}"`) {
-
-                            last_el.outerHTML = tpl_info(data);
-                        } else {
-                            const el = u.stringToElement(tpl_info(data));
-                            this.content.insertAdjacentElement('beforeend', el);
-                            this.insertDayIndicator(el);
-                        }
+                        const el = u.stringToElement(tpl_info(data));
+                        this.content.insertAdjacentElement('beforeend', el);
+                        this.insertDayIndicator(el);
                     }
                     }
                     this.scrollDown();
                     this.scrollDown();
                 },
                 },