Bläddra i källkod

Avoid rendering the controlbox at all when it's hidden

JC Brand 1 år sedan
förälder
incheckning
8d1bb9839f

+ 2 - 1
src/plugins/bookmark-views/tests/bookmarks-list.js

@@ -17,7 +17,8 @@ describe("The bookmarks list modal", function () {
         mock.openControlBox(_converse);
 
         const controlbox = _converse.chatboxviews.get('controlbox');
-        controlbox.querySelector('.show-bookmark-list-modal').click();
+        const button = await u.waitUntil(() => controlbox.querySelector('.show-bookmark-list-modal'));
+        button.click();
 
         const IQ_stanzas = _converse.api.connection.get().IQ_stanzas;
         const sent_stanza = await u.waitUntil(

+ 31 - 25
src/plugins/chatboxviews/templates/chats.js

@@ -4,12 +4,11 @@ import { _converse, api, constants } from '@converse/headless';
 
 const { CONTROLBOX_TYPE, CHATROOMS_TYPE, HEADLINES_TYPE } = constants;
 
-function shouldShowChat (c) {
-    const is_minimized = (api.settings.get('view_mode') === 'overlayed' && c.get('minimized'));
+function shouldShowChat(c) {
+    const is_minimized = api.settings.get('view_mode') === 'overlayed' && c.get('minimized');
     return c.get('type') === CONTROLBOX_TYPE || !(c.get('hidden') || is_minimized);
 }
 
-
 export default () => {
     const { chatboxes } = _converse.state;
     const view_mode = api.settings.get('view_mode');
@@ -17,28 +16,35 @@ export default () => {
     const logged_out = !connection?.connected || !connection?.authenticated || connection?.disconnecting;
     return html`
         ${!logged_out && view_mode === 'overlayed' ? html`<converse-minimized-chats></converse-minimized-chats>` : ''}
-        ${repeat(chatboxes.filter(shouldShowChat), m => m.get('jid'), m => {
-            if (m.get('type') === CONTROLBOX_TYPE) {
-                return html`
-                    ${view_mode === 'overlayed' ? html`<converse-controlbox-toggle class="${!m.get('closed') ? 'hidden' : ''}"></converse-controlbox-toggle>` : ''}
-                    <converse-controlbox
-                        id="controlbox"
-                        class="chatbox ${view_mode === 'overlayed' && m.get('closed') ? 'hidden' : ''} ${logged_out ? 'logged-out': ''}"
-                        style="${m.get('width') ? `width: ${m.get('width')}` : ''}"></converse-controlbox>
-                `;
-            } else if (m.get('type') === CHATROOMS_TYPE) {
-                return html`
-                    <converse-muc jid="${m.get('jid')}" class="chatbox chatroom"></converse-muc>
-                `;
-            } else if (m.get('type') === HEADLINES_TYPE) {
-                return html`
-                    <converse-headlines jid="${m.get('jid')}" class="chatbox headlines"></converse-headlines>
-                `;
-            } else {
-                return html`
-                    <converse-chat jid="${m.get('jid')}" class="chatbox"></converse-chat>
-                `;
+        ${repeat(
+            chatboxes.filter(shouldShowChat),
+            (m) => m.get('jid'),
+            (m) => {
+                if (m.get('type') === CONTROLBOX_TYPE) {
+                    return html`
+                        ${view_mode === 'overlayed'
+                            ? html`<converse-controlbox-toggle
+                                  class="${!m.get('closed') ? 'hidden' : ''}"
+                              ></converse-controlbox-toggle>`
+                            : ''}
+                        <converse-controlbox
+                            id="controlbox"
+                            class="chatbox ${view_mode === 'overlayed' && m.get('closed') ? 'hidden' : ''} ${logged_out
+                                ? 'logged-out'
+                                : ''}"
+                            style="${m.get('width') ? `width: ${m.get('width')}` : ''}"
+                        ></converse-controlbox>
+                    `;
+                } else if (m.get('type') === CHATROOMS_TYPE) {
+                    return html` <converse-muc jid="${m.get('jid')}" class="chatbox chatroom"></converse-muc> `;
+                } else if (m.get('type') === HEADLINES_TYPE) {
+                    return html`
+                        <converse-headlines jid="${m.get('jid')}" class="chatbox headlines"></converse-headlines>
+                    `;
+                } else {
+                    return html` <converse-chat jid="${m.get('jid')}" class="chatbox"></converse-chat> `;
+                }
             }
-        })}
+        )}
     `;
 };

+ 8 - 1
src/plugins/chatview/tests/chatbox.js

@@ -952,10 +952,12 @@ describe("Chatboxes", function () {
 
     describe("A RosterView's Unread Message Count", function () {
 
-        it("is updated when message is received and chatbox is scrolled up",
+        it("is updated when a message is received and chatbox is scrolled up",
                 mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current', 1);
+            await mock.openControlBox(_converse);
+
             let msg, indicator_el;
             const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
             const rosterview = document.querySelector('converse-roster');
@@ -980,6 +982,7 @@ describe("Chatboxes", function () {
                 mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current', 1);
+            await mock.openControlBox(_converse);
             const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
 
             let indicator_el, msg;
@@ -1007,6 +1010,8 @@ describe("Chatboxes", function () {
                 mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current', 1);
+            await mock.openControlBox(_converse);
+
             const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
             const msgFactory = () => mock.createChatMessage(_converse, sender_jid, 'This message will be received as unread, but eventually will be read');
             const rosterview = document.querySelector('converse-roster');
@@ -1054,6 +1059,8 @@ describe("Chatboxes", function () {
                 mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current', 1);
+            await mock.openControlBox(_converse);
+
             const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
             const rosterview = document.querySelector('converse-roster');
             await u.waitUntil(() => rosterview.querySelectorAll('.roster-group').length, 500);

+ 1 - 2
src/plugins/chatview/tests/message-avatar.js

@@ -1,10 +1,9 @@
 /*global mock, converse */
-
 const { u, $msg } = converse.env;
 
 describe("A Chat Message", function () {
 
-    fit("has a default avatar with a XEP-0392 color and initials",
+    it("has a default avatar with a XEP-0392 color and initials",
             mock.initConverse(['chatBoxesFetched'], {}, async function (_converse) {
 
         const { api } = _converse;

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

@@ -918,6 +918,7 @@ describe("A Chat Message", function () {
 
             const { api } = _converse;
             await mock.waitForRoster(_converse, 'current', 1, false);
+            await mock.openControlBox(_converse);
             const rosterview = document.querySelector('converse-roster');
             await u.waitUntil(() => rosterview.querySelectorAll('.roster-group').length, 300);
             const message = '\n\n        This is a received message         \n\n';
@@ -1300,6 +1301,7 @@ describe("A Chat Message", function () {
 
             const { api } = _converse;
             await mock.waitForRoster(_converse, 'current');
+            await mock.openControlBox(_converse);
             const rosterview = document.querySelector('converse-roster');
             await u.waitUntil(() => rosterview.querySelectorAll('.roster-group').length)
             // Send a message from a different resource

+ 11 - 10
src/plugins/controlbox/controlbox.js

@@ -12,8 +12,7 @@ const { LOGOUT } = constants;
  * `view_mode` it's a left-aligned sidebar.
  */
 class ControlBoxView extends CustomElement {
-
-    initialize () {
+    initialize() {
         this.setModel();
         const { chatboxviews } = _converse.state;
         chatboxviews.add('controlbox', this);
@@ -33,26 +32,28 @@ class ControlBoxView extends CustomElement {
         api.trigger('controlBoxInitialized', this);
     }
 
-    setModel () {
+    setModel() {
         this.model = _converse.state.chatboxes.get('controlbox');
         this.listenTo(_converse.state.connfeedback, 'change:connection_status', () => this.requestUpdate());
         this.listenTo(this.model, 'change:active-form', () => this.requestUpdate());
         this.listenTo(this.model, 'change:connected', () => this.requestUpdate());
-        this.listenTo(this.model, 'change:closed', () => !this.model.get('closed') && this.afterShown());
+        this.listenTo(this.model, 'change:closed', () => {
+            this.requestUpdate();
+            if (!this.model.get('closed')) this.afterShown();
+        });
         this.requestUpdate();
     }
 
-    render () {
-        return this.model ? tplControlbox(this) : '';
+    render() {
+        return this.model && !this.model.get('closed') ? tplControlbox(this) : '';
     }
 
-    close (ev) {
+    close(ev) {
         ev?.preventDefault?.();
         const connection = api.connection.get();
         if (
             ev?.name === 'closeAllChatBoxes' &&
-            (connection.disconnection_cause !== LOGOUT ||
-                api.settings.get('show_controlbox_by_default'))
+            (connection.disconnection_cause !== LOGOUT || api.settings.get('show_controlbox_by_default'))
         ) {
             return;
         }
@@ -64,7 +65,7 @@ class ControlBoxView extends CustomElement {
         return this;
     }
 
-    afterShown () {
+    afterShown() {
         /**
          * Triggered once the controlbox has been opened
          * @event _converse#controlBoxOpened

+ 38 - 34
src/plugins/controlbox/templates/controlbox.js

@@ -1,58 +1,62 @@
 /**
  * @typedef {import('../controlbox').default} ControlBoxView
  */
-import tplSpinner from "templates/spinner.js";
-import { _converse, api, converse, constants } from "@converse/headless";
+import tplSpinner from 'templates/spinner.js';
+import { _converse, api, converse, constants } from '@converse/headless';
 import { html } from 'lit';
 
 const { Strophe } = converse.env;
 const { ANONYMOUS } = constants;
 
-
-function whenNotConnected (o) {
+/**
+ * @param {ControlBoxView} el
+ */
+function whenNotConnected(el) {
     const connection_status = _converse.state.connfeedback.get('connection_status');
     if ([Strophe.Status.RECONNECTING, Strophe.Status.CONNECTING].includes(connection_status)) {
         return tplSpinner();
     }
-    if (o['active-form'] === 'register') {
+    if (el.model.get('active-form') === 'register') {
         return html`<converse-register-panel></converse-register-panel>`;
     }
-    return html`<converse-login-form id="converse-login-panel" class="controlbox-pane fade-in row no-gutters"></converse-login-form>`;
+    return html`<converse-login-form
+        id="converse-login-panel"
+        class="controlbox-pane fade-in row no-gutters"
+    ></converse-login-form>`;
 }
 
-
 /**
  * @param {ControlBoxView} el
  */
 export default (el) => {
-    const o = el.model.toJSON();
     const sticky_controlbox = api.settings.get('sticky_controlbox');
 
-    return html`
-        <div class="flyout box-flyout">
-            <converse-dragresize></converse-dragresize>
-            <div class="chat-head controlbox-head">
-                ${sticky_controlbox
-                    ? ''
-                    : html`
-                        <a class="chatbox-btn close-chatbox-button" @click=${(ev) => el.close(ev)}>
-                            <converse-icon class="fa fa-times" size="1em"></converse-icon>
-                        </a>
-                    `}
-            </div>
-            <div class="controlbox-panes">
-                <div class="controlbox-pane">
-                    ${o.connected
-                        ? html`
-                            <converse-user-profile></converse-user-profile>
-                            <converse-headlines-feeds-list class="controlbox-section"></converse-headlines-feeds-list>
-                            <div id="chatrooms" class="controlbox-section"><converse-rooms-list></converse-rooms-list></div>
-                            ${ api.settings.get("authentication") === ANONYMOUS ? '' :
-                                html`<div id="converse-roster" class="controlbox-section"><converse-roster></converse-roster></div>`
-                            }`
-                        : whenNotConnected(o)
-                    }
-                </div>
+    return html` <div class="flyout box-flyout">
+        <converse-dragresize></converse-dragresize>
+        <div class="chat-head controlbox-head">
+            ${sticky_controlbox
+                ? ''
+                : html`
+                      <a class="chatbox-btn close-chatbox-button" @click=${(ev) => el.close(ev)}>
+                          <converse-icon class="fa fa-times" size="1em"></converse-icon>
+                      </a>
+                  `}
+        </div>
+        <div class="controlbox-panes">
+            <div class="controlbox-pane">
+                ${el.model.get('connected')
+                    ? html` <converse-user-profile></converse-user-profile>
+                          <converse-headlines-feeds-list class="controlbox-section"></converse-headlines-feeds-list>
+                          <div id="chatrooms" class="controlbox-section">
+                              <converse-rooms-list></converse-rooms-list>
+                          </div>
+                          ${api.settings.get('authentication') === ANONYMOUS
+                              ? ''
+                              : html`<div id="converse-roster" class="controlbox-section">
+                                    <converse-roster></converse-roster>
+                                </div>`}`
+                    : whenNotConnected(el)}
             </div>
-        </div>`
+        </div>
+    </div>`;
 };

+ 5 - 2
src/plugins/controlbox/tests/login.js

@@ -13,6 +13,8 @@ describe("The Login Form", function () {
 
         const cbview = await u.waitUntil(() => _converse.chatboxviews.get('controlbox'));
         mock.toggleControlBox();
+        await u.waitUntil(() => cbview.querySelectorAll('input[type="checkbox"]').length);
+
         const checkboxes = cbview.querySelectorAll('input[type="checkbox"]');
         expect(checkboxes.length).toBe(1);
 
@@ -44,9 +46,10 @@ describe("The Login Form", function () {
               allow_registration: false },
             async function (_converse) {
 
-        await u.waitUntil(() => _converse.chatboxviews.get('controlbox'))
-        const cbview = _converse.chatboxviews.get('controlbox');
+        const cbview = await u.waitUntil(() => _converse.chatboxviews.get('controlbox'))
         mock.toggleControlBox();
+        await u.waitUntil(() => cbview.querySelectorAll('input[type="checkbox"]').length);
+
         const checkboxes = cbview.querySelectorAll('input[type="checkbox"]');
         expect(checkboxes.length).toBe(1);
 

+ 1 - 1
src/plugins/muc-views/tests/muc-add-modal.js

@@ -23,7 +23,7 @@ describe('The "Groupchats" Add modal', function () {
             const label_nick = modal.querySelector('label[for="nickname"]');
             expect(label_nick.textContent.trim()).toBe('Nickname:');
             const nick_input = modal.querySelector('input[name="nickname"]');
-            expect(nick_input.value).toBe('');
+            expect(nick_input.value).toBe('Romeo');
             nick_input.value = 'romeo';
 
             expect(modal.querySelector('.modal-title').textContent.trim()).toBe('Enter a new Groupchat');

+ 2 - 0
src/plugins/muc-views/tests/muc-api.js

@@ -58,6 +58,8 @@ describe("Groupchats", function () {
                 mock.initConverse([], {}, async function (_converse) {
 
             await mock.waitForRoster(_converse, 'current');
+            await mock.openControlBox(_converse);
+
             const rosterview = document.querySelector('converse-roster');
             await u.waitUntil(() => rosterview.querySelectorAll('.roster-group .group-toggle').length, 300);
             let muc_jid = 'chillout@montague.lit';

+ 9 - 4
src/plugins/muc-views/tests/nickname.js

@@ -427,7 +427,7 @@ describe("A MUC", function () {
             await mock.waitForRoster(_converse, 'current', 0);
             const roomspanel = _converse.chatboxviews.get('controlbox').querySelector('converse-rooms-list');
             roomspanel.querySelector('.show-add-muc-modal').click();
-            mock.closeControlBox(_converse);
+
             const modal = _converse.api.modal.get('converse-add-muc-modal');
             await u.waitUntil(() => u.isVisible(modal), 1000)
             const name_input = modal.querySelector('input[name="chatroom"]');
@@ -441,13 +441,18 @@ describe("A MUC", function () {
         }));
 
         it("uses the JID node if muc_nickname_from_jid is set to true",
-                mock.initConverse(['chatBoxesFetched'], {'muc_nickname_from_jid': true}, async function (_converse) {
+            mock.initConverse(
+                ['chatBoxesFetched'],
+                {
+                    'muc_nickname_from_jid': true,
+                    blacklisted_plugins: ['converse-vcard']
+                }, async function (_converse) {
 
             await mock.openControlBox(_converse);
             await mock.waitForRoster(_converse, 'current', 0);
             const roomspanel = _converse.chatboxviews.get('controlbox').querySelector('converse-rooms-list');
             roomspanel.querySelector('.show-add-muc-modal').click();
-            mock.closeControlBox(_converse);
+
             const modal = _converse.api.modal.get('converse-add-muc-modal');
             await u.waitUntil(() => u.isVisible(modal), 1000)
             const label_nick = modal.querySelector('label[for="nickname"]');
@@ -463,7 +468,7 @@ describe("A MUC", function () {
             await mock.waitForRoster(_converse, 'current', 0);
             const roomspanel = _converse.chatboxviews.get('controlbox').querySelector('converse-rooms-list');
             roomspanel.querySelector('.show-add-muc-modal').click();
-            mock.closeControlBox(_converse);
+
             const modal = _converse.api.modal.get('converse-add-muc-modal');
             await u.waitUntil(() => u.isVisible(modal), 1000)
             const label_nick = modal.querySelector('label[for="nickname"]');

+ 11 - 7
src/plugins/register/tests/register.js

@@ -151,11 +151,10 @@ describe("The Registration Panel", function () {
               allow_registration: true },
             async function (_converse) {
 
-        const toggle = await u.waitUntil(() => document.querySelector(".toggle-controlbox"));
-        toggle.click();
-
+        await mock.toggleControlBox();
         const cbview = _converse.api.controlbox.get();
-        cbview.querySelector('.toggle-register-login').click();
+        const login_form = await u.waitUntil(() => cbview.querySelector('.toggle-register-login'));
+        login_form.click();
 
         const registerview = await u.waitUntil(() => cbview.querySelector('converse-register-panel'));
         spyOn(registerview, 'fetchRegistrationForm').and.callThrough();
@@ -216,7 +215,8 @@ describe("The Registration Panel", function () {
             toggle.click();
         }
         const cbview = _converse.api.controlbox.get();
-        cbview.querySelector('.toggle-register-login').click();
+        const login_form = await u.waitUntil(() => cbview.querySelector('.toggle-register-login'));
+        login_form.click();
 
         const registerview = await u.waitUntil(() => cbview.querySelector('converse-register-panel'));
         spyOn(registerview, 'onProviderChosen').and.callThrough();
@@ -279,7 +279,9 @@ describe("The Registration Panel", function () {
             toggle.click();
         }
         const cbview = _converse.api.controlbox.get();
-        cbview.querySelector('.toggle-register-login').click();
+        const login_form = await u.waitUntil(() => cbview.querySelector('.toggle-register-login'));
+        login_form.click();
+
         const registerview = await u.waitUntil(() => cbview.querySelector('converse-register-panel'));
         spyOn(registerview, 'onProviderChosen').and.callThrough();
         spyOn(registerview, 'getRegistrationFields').and.callThrough();
@@ -359,7 +361,9 @@ describe("The Registration Panel", function () {
             toggle.click();
         }
         const cbview = _converse.chatboxviews.get('controlbox');
-        cbview.querySelector('.toggle-register-login').click();
+        const login_form = await u.waitUntil(() => cbview.querySelector('.toggle-register-login'));
+        login_form.click();
+
         const registerview = await u.waitUntil(() => cbview.querySelector('converse-register-panel'));
         registerview.querySelector('input[name=domain]').value = 'conversejs.org';
         registerview.querySelector('input[type=submit]').click();

+ 3 - 1
src/plugins/rosterview/tests/protocol.js

@@ -56,7 +56,9 @@ describe("The Protocol", function () {
             spyOn(_converse.roster, "sendContactAddIQ").and.callThrough();
             spyOn(_converse.api.vcard, "get").and.callThrough();
 
-            cbview.querySelector('.add-contact').click()
+            const add_contact_button = await u.waitUntil(() => cbview.querySelector('.add-contact'));
+            add_contact_button.click()
+
             const modal = _converse.api.modal.get('converse-add-contact-modal');
             await u.waitUntil(() => u.isVisible(modal), 1000);
             modal.delegateEvents();

+ 3 - 0
src/plugins/rosterview/tests/roster.js

@@ -195,6 +195,7 @@ describe("The Contacts Roster", function () {
 
         await u.waitUntil(() => _converse.roster.length === 2);
         expect(_converse.roster.pluck('jid')).toEqual(['juliet@example.net', 'mercutio@example.net']);
+        await mock.openControlBox(_converse);
 
         const rosterview = document.querySelector('converse-roster');
 
@@ -1305,6 +1306,8 @@ describe("The Contacts Roster", function () {
         it("are persisted even if other contacts' change their presence ", mock.initConverse(
             [], {}, async function (_converse) {
 
+            await mock.openControlBox(_converse);
+
             const sent_IQs = _converse.api.connection.get().IQ_stanzas;
             const stanza = await u.waitUntil(() => sent_IQs.filter(iq => iq.querySelector('iq query[xmlns="jabber:iq:roster"]')).pop());
             // Taken from the spec