Browse Source

Let message component listen for changes...

and render directly from those

Instead of doing it higher up in the chat view (which requires more
function calls and iterating through all messages).
JC Brand 4 years ago
parent
commit
65ad33ec81
7 changed files with 39 additions and 19 deletions
  1. 1 1
      dev.html
  2. 1 2
      spec/messages.js
  3. 1 1
      spec/retractions.js
  4. 1 1
      spec/spoilers.js
  5. 19 13
      src/components/message-history.js
  6. 16 0
      src/components/message.js
  7. 0 1
      src/converse-chatview.js

+ 1 - 1
dev.html

@@ -35,7 +35,7 @@
         muc_respect_autojoin: true,
         muc_show_logs_before_join: true,
         notify_all_room_messages: ['discuss@conference.conversejs.org'],
-        persistent_store: 'IndexedDB',
+        persistent_store: 'localStorage',
         theme: 'concord',
         view_mode: 'fullscreen',
         websocket_url: 'wss://conversejs.org/xmpp-websocket',

+ 1 - 2
spec/messages.js

@@ -344,8 +344,7 @@ describe("A Chat Message", function () {
             keyCode: 13 // Enter
         });
         await new Promise(resolve => view.model.messages.once('rendered', resolve));
-
-        expect(textarea.value).toBe('');
+        await u.waitUntil(() => textarea.value === '');
         const messages = view.el.querySelectorAll('.chat-msg');
         expect(messages.length).toBe(3);
         expect(messages[0].querySelector('.chat-msg__text').textContent)

+ 1 - 1
spec/retractions.js

@@ -1,4 +1,4 @@
-/*global mock */
+/*global mock, converse */
 
 const { Strophe, $iq } = converse.env;
 const u = converse.env.utils;

+ 1 - 1
spec/spoilers.js

@@ -1,4 +1,4 @@
-/* global mock */
+/* global mock, converse */
 
 const original_timeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
 

+ 19 - 13
src/components/message-history.js

@@ -81,6 +81,19 @@ function getHats (model) {
 }
 
 
+export function getDerivedMessageProps (chatbox, model) {
+    const is_groupchat = model.get('type') === 'groupchat';
+    return {
+        'has_mentions': is_groupchat && model.get('sender') === 'them' && chatbox.isUserMentioned(model),
+        'hats': getHats(model),
+        'is_first_unread': chatbox.get('first_unread_id') === model.get('id'),
+        'is_me_message': model.isMeCommand(),
+        'is_retracted': model.get('retracted') || model.get('moderated') === 'retracted',
+        'username': model.getDisplayName(),
+    }
+}
+
+
 export default class MessageHistory extends CustomElement {
 
     static get properties () {
@@ -104,20 +117,13 @@ export default class MessageHistory extends CustomElement {
         }
         const day = getDayIndicator(model);
         const templates = day ? [day] : [];
-        const is_groupchat = model.get('type') === 'groupchat';
-        const chatbox = this.chatview.model;
         const message = tpl_message(
-            Object.assign(model.toJSON(), {
-                'chatview': this.chatview,
-                'has_mentions': is_groupchat && model.get('sender') === 'them' && chatbox.isUserMentioned(model),
-                'hats': getHats(model),
-                'is_first_unread': chatbox.get('first_unread_id') === model.get('id'),
-                'is_me_message': model.isMeCommand(),
-                'is_retracted': model.get('retracted') || model.get('moderated') === 'retracted',
-                'occupant': model.occupant,
-                'username': model.getDisplayName(),
-                model,
-            }));
+            Object.assign(
+                model.toJSON(),
+                getDerivedMessageProps(this.chatview.model, model),
+                { 'chatview': this.chatview, model }
+            )
+        );
         return [...templates, message];
     }
 }

+ 16 - 0
src/components/message.js

@@ -2,6 +2,7 @@ import './message-body.js';
 import '../converse-registry';
 import './dropdown.js';
 import './message-actions.js';
+import { getDerivedMessageProps } from './message-history';
 import MessageVersionsModal from '../modals/message-versions.js';
 import dayjs from 'dayjs';
 import filesize from 'filesize';
@@ -74,6 +75,21 @@ export default class Message extends CustomElement {
         }
     }
 
+    connectedCallback () {
+        super.connectedCallback();
+        // Listen to changes and update properties (which will trigger a
+        // re-render if necessary).
+        this.listenTo(this.model, 'change', (model) => {
+            const chatbox = this.model.collection.chatbox;
+            Object.assign(this, getDerivedMessageProps(chatbox, this.model));
+            Object.keys(model.changed)
+                .filter(p => Object.keys(Message.properties).includes(p))
+                .forEach(p => (this[p] = model.changed[p]));
+        });
+        const vcard = this.model.vcard;
+        vcard && this.listenTo(vcard, 'change', () => this.requestUpdate());
+    }
+
     updated () {
         // XXX: This is ugly but tests rely on this event.
         // For "normal" chat messages the event is fired in

+ 0 - 1
src/converse-chatview.js

@@ -74,7 +74,6 @@ export const ChatBoxView = View.extend({
 
         // Need to be registered after render has been called.
         this.listenTo(this.model.messages, 'add', this.onMessageAdded);
-        this.listenTo(this.model.messages, 'change', this.renderChatHistory);
         this.listenTo(this.model.messages, 'remove', this.renderChatHistory);
         this.listenTo(this.model.messages, 'rendered', this.maybeScrollDown);
         this.listenTo(this.model.messages, 'reset', this.renderChatHistory);