Răsfoiți Sursa

Fix: In chatbox heading two avatars sometimes get rendered

JC Brand 7 ani în urmă
părinte
comite
bac1d22205

+ 1 - 0
CHANGES.md

@@ -7,6 +7,7 @@
 - #949 Don't flash the roster contacts filter (i.e. hide by default)
 - Don't require `auto_login` to be `true` when using the API to log in.
 - Moment locale wasn't being set to the value passed via the `i18n` option.
+- In the chat heading, two avatars sometimes get rendered.
 - Refetch the roster from the server after reconnection.
   From the perspective of the XMPP server, this is an entirely new login,
   and therefore as per [RFC-6121](https://tools.ietf.org/html/rfc6121#section-2.1.6)

+ 90 - 74
src/converse-chatview.js

@@ -14,13 +14,13 @@
             "emojione",
             "xss",
             "tpl!chatbox",
+            "tpl!chatbox_head",
             "tpl!new_day",
             "tpl!action",
             "tpl!emojis",
             "tpl!message",
             "tpl!help_message",
             "tpl!toolbar",
-            "tpl!avatar",
             "tpl!spinner"
     ], factory);
 }(this, function (
@@ -30,13 +30,13 @@
             emojione,
             xss,
             tpl_chatbox,
+            tpl_chatbox_head,
             tpl_new_day,
             tpl_action,
             tpl_emojis,
             tpl_message,
             tpl_help_message,
             tpl_toolbar,
-            tpl_avatar,
             tpl_spinner
     ) {
     "use strict";
@@ -218,9 +218,68 @@
                 }
             });
 
+            _converse.ChatBoxHeading = Backbone.VDOMView.extend({
+
+                initialize () {
+                    this.model.on('change:image', this.setAvatar, this);
+                    this.model.on('change:status', this.onStatusMessageChanged, this);
+                    this.model.on('change:fullname', this.render, this);
+                    this.initializeAvatar();
+                },
+
+                renderHTML () {
+                    return tpl_chatbox_head(
+                        _.extend(this.model.toJSON(), {
+                            'avatar_width': _converse.chatview_avatar_width,
+                            'avatar_height': _converse.chatview_avatar_height,
+                            'info_close': __('Close this chat box'),
+                        })
+                    );
+                },
+
+                afterRender () {
+                    this.setAvatar();
+                },
+
+                setAvatar () {
+                    this.avatar.src = `data:${this.model.get('image_type')};base64,${this.model.get('image')}`;
+                },
+
+                initializeAvatar () {
+                    var that = this;
+                    this.avatar = new Image();
+                    this.avatar.onload = function () {
+                        const canvas = that.el.querySelector('canvas');
+                        const avatar_width = _converse.chatview_avatar_width;
+                        const avatar_height = _converse.chatview_avatar_height;
+
+                        // XXX: this seems to be needed to work around the
+                        // chrome setting width/height to 0 (possible due to
+                        // no canvas data being there?)
+                        canvas.setAttribute('width', avatar_width);
+                        canvas.setAttribute('height', avatar_height);
+
+                        const ctx = canvas.getContext('2d');
+                        const ratio = this.width/this.height;
+                        if (ratio < 1) {
+                            ctx.drawImage(this, 0,0, avatar_width, avatar_height*(1/ratio));
+                        } else {
+                            ctx.drawImage(this, 0,0, avatar_width, avatar_height*ratio);
+                        }
+                    };
+                },
+
+                onStatusMessageChanged (item) {
+                    this.render();
+                    _converse.emit('contactStatusMessageChanged', {
+                        'contact': item.attributes,
+                        'message': item.get('status')
+                    });
+                }
+            });
+
             _converse.ChatBoxView = Backbone.View.extend({
                 length: 200,
-                tagName: 'div',
                 className: 'chatbox hidden',
                 is_chatroom: false,  // Leaky abstraction from MUC
 
@@ -237,43 +296,47 @@
 
                 initialize () {
                     this.markScrolled = _.debounce(this.markScrolled, 100);
-
                     this.createEmojiPicker();
                     this.model.messages.on('add', this.onMessageAdded, this);
                     this.model.on('show', this.show, this);
-                    this.model.on('destroy', this.hide, this);
+                    this.model.on('destroy', this.remove, this);
                     // TODO check for changed fullname as well
                     this.model.on('change:chat_state', this.sendChatState, this);
                     this.model.on('change:chat_status', this.onChatStatusChanged, this);
-                    this.model.on('change:image', this.renderAvatar, this);
-                    this.model.on('change:status', this.onStatusChanged, this);
                     this.model.on('showHelpMessages', this.showHelpMessages, this);
                     this.model.on('sendMessage', this.sendMessage, this);
-                    this.render().fetchMessages();
+
+                    this.heading = new _converse.ChatBoxHeading({'model': this.model});
+                    this.heading.render();
+                    this.heading.chatview = this;
+
+                    this.render().renderToolbar().insertHeading().fetchMessages();
+                    utils.refreshWebkit();
+                    _converse.emit('chatBoxOpened', this);
                     _converse.emit('chatBoxInitialized', this);
                 },
 
                 render () {
-                    this.$el.attr('id', this.model.get('box_id'))
-                        .html(tpl_chatbox(
-                                _.extend(this.model.toJSON(), {
-                                        show_toolbar: _converse.show_toolbar,
-                                        show_textarea: true,
-                                        show_send_button: _converse.show_send_button,
-                                        title: this.model.get('fullname'),
-                                        unread_msgs: __('You have unread messages'),
-                                        info_close: __('Close this chat box'),
-                                        label_personal_message: __('Personal message'),
-                                        label_send: __('Send')
-                                    }
-                                )
-                            )
-                        );
+                    this.el.setAttribute('id', this.model.get('box_id'));
+                    this.el.innerHTML = tpl_chatbox(
+                        _.extend(this.model.toJSON(), {
+                                show_toolbar: _converse.show_toolbar,
+                                show_textarea: true,
+                                show_send_button: _converse.show_send_button,
+                                unread_msgs: __('You have unread messages'),
+                                label_personal_message: __('Personal message'),
+                                label_send: __('Send')
+                            }
+                        )
+                    );
                     this.$content = this.$el.find('.chat-content');
-                    this.renderToolbar().renderAvatar();
-                    _converse.emit('chatBoxOpened', this);
-                    utils.refreshWebkit();
-                    return this.showStatusMessage();
+                    return this;
+                },
+
+                insertHeading () {
+                    const flyout = this.el.querySelector('.flyout');
+                    flyout.insertBefore(this.heading.el, flyout.querySelector('.chat-body'));
+                    return this;
                 },
 
                 createEmojiPicker () {
@@ -816,22 +879,6 @@
                     }
                 },
 
-                onStatusChanged (item) {
-                    this.showStatusMessage();
-                    _converse.emit('contactStatusMessageChanged', {
-                        'contact': item.attributes,
-                        'message': item.get('status')
-                    });
-                },
-
-                showStatusMessage (msg) {
-                    msg = msg || this.model.get('status');
-                    if (_.isString(msg)) {
-                        this.$el.find('p.user-custom-message').text(msg).attr('title', msg);
-                    }
-                    return this;
-                },
-
                 close (ev) {
                     if (ev && ev.preventDefault) { ev.preventDefault(); }
                     if (Backbone.history.getFragment() === "converse/chat?jid="+this.model.get('jid')) {
@@ -879,37 +926,6 @@
                     return this;
                 },
 
-                renderAvatar () {
-                    if (!this.model.get('image')) {
-                        return;
-                    }
-                    const width = _converse.chatview_avatar_width;
-                    const height = _converse.chatview_avatar_height;
-                    const img_src = `data:${this.model.get('image_type')};base64,${this.model.get('image')}`,
-                        canvas = $(tpl_avatar({
-                            'width': width,
-                            'height': height
-                        })).get(0);
-
-                    if (!(canvas.getContext && canvas.getContext('2d'))) {
-                        return this;
-                    }
-                    const ctx = canvas.getContext('2d');
-                    const img = new Image();   // Create new Image object
-                    img.onload = function () {
-                        const ratio = img.width/img.height;
-                        if (ratio < 1) {
-                            ctx.drawImage(img, 0,0, width, height*(1/ratio));
-                        } else {
-                            ctx.drawImage(img, 0,0, width, height*ratio);
-                        }
-
-                    };
-                    img.src = img_src;
-                    this.$el.find('.chat-title').before(canvas);
-                    return this;
-                },
-
                 focus () {
                     this.el.querySelector('.chat-textarea').focus();
                     _converse.emit('chatBoxFocused', this);

+ 0 - 1
src/templates/avatar.html

@@ -1 +0,0 @@
-<canvas height="{{o.height}}px" width="{{o.width}}px" class="avatar"></canvas>

+ 7 - 21
src/templates/chatbox.html

@@ -1,17 +1,4 @@
 <div class="flyout box-flyout">
-    <div class="chat-head chat-head-chatbox">
-        <a class="chatbox-btn close-chatbox-button icon-close" title="{{{o.info_close}}}"></a>
-        <div class="chat-title">
-            {[ if (o.url) { ]}
-                <a href="{{{o.url}}}" target="_blank" rel="noopener" class="user">
-            {[ } ]}
-                    {{{ o.title }}}
-            {[ if (o.url) { ]}
-                </a>
-            {[ } ]}
-            <p class="user-custom-message"><p/>
-        </div>
-    </div>
     <div class="chat-body">
         <div class="chat-content {[ if (o.show_send_button) { ]}chat-content-sendbutton{[ } ]}"></div>
         <div class="new-msgs-indicator hidden">▼ {{{ o.unread_msgs }}} ▼</div>
@@ -20,14 +7,13 @@
             {[ if (o.show_toolbar) { ]}
                 <ul class="chat-toolbar no-text-select"></ul>
             {[ } ]}
-        <textarea
-            type="text"
-            class="chat-textarea {[ if (o.show_send_button) { ]}chat-textarea-send-button{[ } ]}"
-            placeholder="{{{o.label_personal_message}}}"/>
-
-        {[ if (o.show_send_button) { ]}
-            <button type="submit" class="pure-button send-button">{{{ o.label_send }}}</button>
-        {[ } ]}
+            <textarea
+                type="text"
+                class="chat-textarea {[ if (o.show_send_button) { ]}chat-textarea-send-button{[ } ]}"
+                placeholder="{{{o.label_personal_message}}}"></textarea>
+            {[ if (o.show_send_button) { ]}
+                <button type="submit" class="pure-button send-button">{{{ o.label_send }}}</button>
+            {[ } ]}
         </form>
         {[ } ]}
     </div>

+ 14 - 0
src/templates/chatbox_head.html

@@ -0,0 +1,14 @@
+<div class="chat-head chat-head-chatbox">
+    <a class="chatbox-btn close-chatbox-button icon-close" title="{{{o.info_close}}}"></a>
+    <canvas height="{{{o.avatar_height}}}px" width="{{{o.avatar_width}}}px" class="avatar"></canvas>
+    <div class="chat-title">
+        {[ if (o.url) { ]}
+            <a href="{{{o.url}}}" target="_blank" rel="noopener" class="user">
+        {[ } ]}
+                {{{ o.fullname }}}
+        {[ if (o.url) { ]}
+            </a>
+        {[ } ]}
+        <p class="user-custom-message">{{{ o.status }}}</p>
+    </div>
+</div>