2
0
Эх сурвалжийг харах

Render chat state notifications on the message view

and not via the chatbox view (fixes some failing tests also).
JC Brand 7 жил өмнө
parent
commit
6ac1df43e1

+ 40 - 27
spec/chatbox.js

@@ -718,25 +718,30 @@
                             }).c('body').c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree();
                         _converse.chatboxes.onMessage(msg);
                         expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object));
-                        var chatboxview = _converse.chatboxviews.get(sender_jid);
-                        expect(chatboxview).toBeDefined();
-                        // Check that the notification appears inside the chatbox in the DOM
-                        var events = chatboxview.el.querySelectorAll('.chat-state-notification');
-                        expect(events.length).toBe(1);
-                        expect(events[0].textContent).toEqual(mock.cur_names[1] + ' is typing');
-
-                        // Check that it doesn't appear twice
-                        msg = $msg({
-                                from: sender_jid,
-                                to: _converse.connection.jid,
-                                type: 'chat',
-                                id: (new Date()).getTime()
-                            }).c('body').c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree();
-                        _converse.chatboxes.onMessage(msg);
-                        events = chatboxview.el.querySelectorAll('.chat-state-notification');
-                        expect(events.length).toBe(1);
-                        expect(events[0].textContent).toEqual(mock.cur_names[1] + ' is typing');
-                        done();
+                        var view = _converse.chatboxviews.get(sender_jid);
+                        expect(view).toBeDefined();
+
+                        test_utils.waitUntil(() => view.model.vcard.get('fullname') === mock.cur_names[1])
+                        .then(function () {
+                            var view = _converse.chatboxviews.get(sender_jid);
+                            // Check that the notification appears inside the chatbox in the DOM
+                            var events = view.el.querySelectorAll('.chat-state-notification');
+                            expect(events.length).toBe(1);
+                            expect(events[0].textContent).toEqual(mock.cur_names[1] + ' is typing');
+
+                            // Check that it doesn't appear twice
+                            msg = $msg({
+                                    from: sender_jid,
+                                    to: _converse.connection.jid,
+                                    type: 'chat',
+                                    id: (new Date()).getTime()
+                                }).c('body').c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree();
+                            _converse.chatboxes.onMessage(msg);
+                            events = view.el.querySelectorAll('.chat-state-notification');
+                            expect(events.length).toBe(1);
+                            expect(events[0].textContent).toEqual(mock.cur_names[1] + ' is typing');
+                            done();
+                        })
                     }));
 
                     it("can be a composing carbon message that this user sent from a different client",
@@ -877,10 +882,14 @@
                                 }).c('body').c('paused', {'xmlns': Strophe.NS.CHATSTATES}).tree();
                             _converse.chatboxes.onMessage(msg);
                             expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object));
-                            var chatboxview = _converse.chatboxviews.get(sender_jid);
-                            var $events = $(chatboxview.el).find('.chat-info.chat-state-notification');
-                            expect($events.text()).toEqual(mock.cur_names[1] + ' has stopped typing');
-                            done();
+                            var view = _converse.chatboxviews.get(sender_jid);
+                            test_utils.waitUntil(() => view.model.vcard.get('fullname') === mock.cur_names[1])
+                            .then(function () {
+                                var view = _converse.chatboxviews.get(sender_jid);
+                                var event = view.el.querySelector('.chat-info.chat-state-notification');
+                                expect(event.textContent).toEqual(mock.cur_names[1] + ' has stopped typing');
+                                done();
+                            });
                         });
                     }));
 
@@ -1113,10 +1122,14 @@
                             }).c('body').c('gone', {'xmlns': Strophe.NS.CHATSTATES}).tree();
                         _converse.chatboxes.onMessage(msg);
                         expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object));
-                        var chatboxview = _converse.chatboxviews.get(sender_jid);
-                        var $events = $(chatboxview.el).find('.chat-state-notification');
-                        expect($events.text()).toEqual(mock.cur_names[1] + ' has gone away');
-                        done();
+                        var view = _converse.chatboxviews.get(sender_jid);
+                        test_utils.waitUntil(() => view.model.vcard.get('fullname') === mock.cur_names[1])
+                        .then(function () {
+                            var view = _converse.chatboxviews.get(sender_jid);
+                            var event = view.el.querySelector('.chat-state-notification');
+                            expect(event.textContent).toEqual(mock.cur_names[1] + ' has gone away');
+                            done();
+                        });
                     }));
                 });
             });

+ 10 - 0
src/converse-chatboxes.js

@@ -109,6 +109,16 @@
                             this.getRequestSlotURL();
                         }
                     }
+                    if (this.isOnlyChatStateNotification()) {
+                        window.setTimeout(this.destroy.bind(this), 20000);
+                    }
+                },
+
+                isOnlyChatStateNotification () {
+                    return this.get('chat_state') &&
+                            !this.get('oob_url') &&
+                            !this.get('file') &&
+                            !this.get('message');
                 },
 
                 getDisplayName () {

+ 3 - 59
src/converse-chatview.js

@@ -14,7 +14,6 @@
             "tpl!chatbox",
             "tpl!chatbox_head",
             "tpl!chatbox_message_form",
-            "tpl!csn",
             "tpl!emojis",
             "tpl!error_message",
             "tpl!help_message",
@@ -37,7 +36,6 @@
             tpl_chatbox,
             tpl_chatbox_head,
             tpl_chatbox_message_form,
-            tpl_csn,
             tpl_emojis,
             tpl_error_message,
             tpl_help_message,
@@ -589,48 +587,6 @@
                     }
                 },
 
-                showChatStateNotification (message) {
-                    /* Support for XEP-0085, Chat State Notifications */
-                    let text;
-                    const from = message.get('from'),
-                          name = message.getDisplayName();
-
-                    this.clearChatStateNotification(message);
-
-                    if (message.get('chat_state') === _converse.COMPOSING) {
-                        if (message.get('sender') === 'me') {
-                            text = __('Typing from another device');
-                        } else {
-                            text = name +' '+__('is typing');
-                        }
-                    } else if (message.get('chat_state') === _converse.PAUSED) {
-                        if (message.get('sender') === 'me') {
-                            text = __('Stopped typing on the other device');
-                        } else {
-                            text = name +' '+__('has stopped typing');
-                        }
-                    } else if (message.get('chat_state') === _converse.GONE) {
-                        text = name +' '+__('has gone away');
-                    } else {
-                        return;
-                    }
-                    const isodate = moment().format();
-                    this.content.insertAdjacentHTML(
-                        'beforeend',
-                        tpl_csn({
-                            'message': text,
-                            'from': from,
-                            'isodate': isodate
-                        }));
-                    this.scrollDown();
-
-                    this.clear_status_timeout = window.setTimeout(
-                        this.clearChatStateNotification.bind(this, message, isodate),
-                        30000
-                    );
-                    return message;
-                },
-
                 shouldShowOnTextMessage () {
                     return !u.isVisible(this.el);
                 },
@@ -711,9 +667,9 @@
                      *  (Backbone.Model) message: The message object
                      */
                     const view = new _converse.MessageView({'model': message});
+                    this.clearChatStateNotification(message);
                     this.insertMessage(view);
                     this.insertDayIndicator(view.el);
-                    this.clearChatStateNotification(message);
                     this.setScrollPosition(view.el);
 
                     if (u.isNewMessage(message)) {
@@ -740,20 +696,8 @@
                      * Parameters:
                      *    (Object) message - The message Backbone object that was added.
                      */
-                    if (!_.isUndefined(this.clear_status_timeout)) {
-                        window.clearTimeout(this.clear_status_timeout);
-                        delete this.clear_status_timeout;
-                    }
-                    if (message.get('type') === 'error') {
-                        this.showMessage(message);
-                    } else {
-                        if (message.get('chat_state') && !message.get('delayed')) {
-                            this.showChatStateNotification(message);
-                        }
-                        if (message.get('file') || message.get('message')) {
-                            this.showMessage(message);
-                        }
-                    }
+                    this.showMessage(message);
+
                     _converse.emit('messageAdded', {
                         'message': message,
                         'chatbox': this.model

+ 57 - 13
src/converse-message-view.js

@@ -11,6 +11,7 @@
         "emojione",
         "filesize",
         "tpl!action",
+        "tpl!csn",
         "tpl!file_progress",
         "tpl!info",
         "tpl!message",
@@ -22,6 +23,7 @@
         emojione,
         filesize,
         tpl_action,
+        tpl_csn,
         tpl_file_progress,
         tpl_info,
         tpl_message,
@@ -74,15 +76,31 @@
                     this.model.on('change:progress', this.renderFileUploadProgresBar, this);
                     this.model.on('change:type', this.render, this);
                     this.model.on('change:upload', this.render, this);
+                    this.model.on('destroy', this.remove, this);
                     this.render();
                 },
 
                 render () {
-                    if (this.model.get('file') && !this.model.get('oob_url')) {
+                    if (this.model.isOnlyChatStateNotification()) {
+                        return this.renderChatStateNotification()
+                    } else if (this.model.get('file') && !this.model.get('oob_url')) {
                         return this.renderFileUploadProgresBar();
                     } else if (this.model.get('type') === 'error') {
                         return this.renderErrorMessage();
+                    } else {
+                        return this.renderChatMessage();
+                    }
+                },
+
+                replaceElement (msg) {
+                    if (!_.isNil(this.el.parentElement)) {
+                        this.el.parentElement.replaceChild(msg, this.el);
                     }
+                    this.setElement(msg);
+                    return this.el;
+                },
+
+                renderChatMessage () {
                     let template, text = this.model.get('message');
                     if (this.isMeCommand()) {
                         template = tpl_action;
@@ -104,13 +122,11 @@
 
                     var url = this.model.get('oob_url');
                     if (url) {
-                        const msg_media = msg.querySelector('.chat-msg-media');
-                        msg_media.innerHTML = _.flow(
+                        msg.querySelector('.chat-msg-media').innerHTML = _.flow(
                             _.partial(u.renderFileURL, _converse),
                             _.partial(u.renderMovieURL, _converse),
                             _.partial(u.renderAudioURL, _converse),
-                            _.partial(u.renderImageURL, _converse)
-                        )(url);
+                            _.partial(u.renderImageURL, _converse))(url);
                     }
 
                     const msg_content = msg.querySelector('.chat-msg-text');
@@ -126,19 +142,12 @@
                         this.model.collection.trigger('rendered');
                     });
                     this.replaceElement(msg);
+
                     if (this.model.get('type') !== 'headline') {
                         this.renderAvatar();
                     }
                 },
 
-                replaceElement (msg) {
-                    if (!_.isNil(this.el.parentElement)) {
-                        this.el.parentElement.replaceChild(msg, this.el);
-                    }
-                    this.setElement(msg);
-                    return this.el;
-                },
-
                 renderErrorMessage () {
                     const moment_time = moment(this.model.get('time')),
                           msg = u.stringToElement(
@@ -150,6 +159,41 @@
                     return this.replaceElement(msg);
                 },
 
+                renderChatStateNotification () {
+                    if (this.model.get('delayed')) {
+                        return this.model.destroy();
+                    }
+                    let text;
+                    const from = this.model.get('from'),
+                          name = this.model.getDisplayName();
+
+                    if (this.model.get('chat_state') === _converse.COMPOSING) {
+                        if (this.model.get('sender') === 'me') {
+                            text = __('Typing from another device');
+                        } else {
+                            text = name +' '+__('is typing');
+                        }
+                    } else if (this.model.get('chat_state') === _converse.PAUSED) {
+                        if (this.model.get('sender') === 'me') {
+                            text = __('Stopped typing on the other device');
+                        } else {
+                            text = name +' '+__('has stopped typing');
+                        }
+                    } else if (this.model.get('chat_state') === _converse.GONE) {
+                        text = name +' '+__('has gone away');
+                    } else {
+                        return;
+                    }
+                    const isodate = moment().format();
+                    this.replaceElement(
+                          u.stringToElement(
+                            tpl_csn({
+                                'message': text,
+                                'from': from,
+                                'isodate': isodate
+                            })));
+                },
+
                 renderFileUploadProgresBar () {
                     const msg = u.stringToElement(tpl_file_progress(
                         _.extend(this.model.toJSON(), {