Bladeren bron

Render chat messages loading spinner declaratively

instead of imperatively.

Add new non-persisted UI model for rendering UI changes. Currently only
being used for rendering the spinner
JC Brand 4 jaren geleden
bovenliggende
commit
ec93e2fff3

+ 5 - 0
src/headless/plugins/chat/model.js

@@ -56,6 +56,7 @@ const ChatBox = ModelWithContact.extend({
         this.set({'box_id': `box-${jid}`});
         this.initNotifications();
         this.initMessages();
+        this.initUI();
 
         if (this.get('type') === _converse.PRIVATE_CHAT_TYPE) {
             this.presence = _converse.presences.findWhere({'jid': jid}) || _converse.presences.create({'jid': jid});
@@ -106,6 +107,10 @@ const ChatBox = ModelWithContact.extend({
         });
     },
 
+    initUI () {
+        this.ui = new Model();
+    },
+
     initNotifications () {
         this.notifications = new Model();
     },

+ 1 - 0
src/headless/plugins/muc/muc.js

@@ -90,6 +90,7 @@ const ChatRoomMixin = {
         this.set('box_id', `box-${this.get('jid')}`);
         this.initNotifications();
         this.initMessages();
+        this.initUI();
         this.initOccupants();
         this.initDiscoModels(); // sendChatState depends on this.features
         this.registerHandlers();

+ 1 - 2
src/plugins/chatview/tests/messages.js

@@ -188,7 +188,6 @@ describe("A Chat Message", function () {
         await _converse.handleMessageStanza(msg);
         await u.waitUntil(() => view.querySelectorAll('.chat-msg').length === 7);
 
-        view.clearSpinner(); //cleanup
         expect(view.querySelectorAll('.date-separator').length).toEqual(4);
 
         let day = sizzle('.date-separator:first', view).pop();
@@ -704,7 +703,7 @@ describe("A Chat Message", function () {
         jasmine.clock().tick(1*ONE_MINUTE_LATER);
         await mock.sendMessage(view, "Another message within 10 minutes, but from a different person");
 
-        expect(view.querySelectorAll('.message').length).toBe(6);
+        await u.waitUntil(() => view.querySelectorAll('.message').length === 6);
         expect(view.querySelectorAll('.chat-msg').length).toBe(5);
 
         const nth_child = (n) => `converse-chat-message:nth-child(${n}) .chat-msg`;

+ 2 - 2
src/plugins/mam-views/utils.js

@@ -8,13 +8,13 @@ export async function fetchMessagesOnScrollUp (view) {
         if (oldest_message) {
             const by_jid = is_groupchat ? view.model.get('jid') : _converse.bare_jid;
             const stanza_id = oldest_message && oldest_message.get(`stanza_id ${by_jid}`);
-            view.addSpinner();
+            view.model.ui.set('chat-content-spinner-top', true);
             if (stanza_id) {
                 await fetchArchivedMessages(view.model, { 'before': stanza_id });
             } else {
                 await fetchArchivedMessages(view.model, { 'end': oldest_message.get('time') });
             }
-            view.clearSpinner();
+            view.model.ui.set('chat-content-spinner-top', false);
             if (api.settings.get('allow_url_history_change')) {
                 _converse.router.history.navigate(`#${oldest_message.get('msgid')}`);
             }

+ 0 - 18
src/shared/chat/baseview.js

@@ -1,6 +1,5 @@
 import debounce from 'lodash-es/debounce';
 import log from '@converse/headless/log';
-import tpl_spinner from 'templates/spinner.js';
 import { ElementView } from '@converse/skeletor/src/element.js';
 import { _converse, api, converse } from '@converse/headless/core';
 
@@ -92,23 +91,6 @@ export default class BaseChatView extends ElementView {
         }
     }
 
-    addSpinner (append = false) {
-        const content = this.querySelector('.chat-content');
-        if (this.querySelector('.spinner') === null) {
-            const el = u.getElementFromTemplateResult(tpl_spinner());
-            if (append) {
-                content.insertAdjacentElement('beforeend', el);
-                this.scrollDown();
-            } else {
-                content.insertAdjacentElement('afterbegin', el);
-            }
-        }
-    }
-
-    clearSpinner () {
-        this.querySelectorAll('.chat-content .spinner').forEach(u.removeElement);
-    }
-
     onStatusMessageChanged (item) {
         this.renderHeading();
         /**

+ 2 - 1
src/shared/chat/chat-content.js

@@ -21,10 +21,10 @@ export default class ChatContent extends CustomElement {
         this.listenTo(this.model.messages, 'remove', this.requestUpdate);
         this.listenTo(this.model.messages, 'reset', this.requestUpdate);
         this.listenTo(this.model.notifications, 'change', this.requestUpdate);
+        this.listenTo(this.model.ui, 'change', this.requestUpdate);
         if (this.model.occupants) {
             this.listenTo(this.model.occupants, 'change', this.requestUpdate);
         }
-
         // We jot down whether we were scrolled down before rendering, because when an
         // image loads, it triggers 'scroll' and the chat will be marked as scrolled,
         // which is technically true, but not what we want because the user
@@ -37,6 +37,7 @@ export default class ChatContent extends CustomElement {
 
     render () {
         return html`
+            ${ this.model.ui.get('chat-content-spinner-top') ? html`<span class="spinner fa fa-spinner centered"></span>` : '' }
             <converse-message-history
                 .model=${this.model}
                 .messages=${[...this.model.messages.models]}>

+ 1 - 0
webpack.html

@@ -40,6 +40,7 @@
             // bosh_service_url: 'http://chat.example.org:5280/http-bind',
             muc_show_logs_before_join: true,
             whitelisted_plugins: ['converse-debug', 'converse-batched-probe'],
+            blacklisted_plugins: [],
         });
     });
 </script>