Browse Source

Improvements to rendering MUC MAM logs before joining

- Add config variable `muc_show_logs_before_join`
- Restore nickname form for the original use-case (when not showing MAM logs before joining).
- Render nickname form in the `.muc-bottom-panel` when showing MAM logs (instead of in a modal)
- Show a message when there aren't any archived messages to show
- Fix converse-mam so that chat logs are properly fetched before entering a MUC

closes #1266
JC Brand 5 years ago
parent
commit
d7d810ba89

+ 3 - 2
CHANGES.md

@@ -10,9 +10,10 @@
   To add custom emojis, edit the `emojis.json` file.
 - Refactor some presence and status handling code from `converse-core` into `@converse/headless/converse-status`.
 - New API [\_converse.api.headlines](https://conversejs.org/docs/html/api/-_converse.api.headlines.html#.get)
-- New config option [muc-mention-autocomplete-filter](https://conversejs.org/docs/html/configuration.html#muc-mention-autocomplete-filter)
-- New config option [muc-mention-autocomplete-show-avatar](https://conversejs.org/docs/html/configuration.html#muc-mention-autocomplete-show-avatar)
 - New config option [allow_message_retraction](https://conversejs.org/docs/html/configuration.html#allow-message-retraction)
+- New config option [muc-show-logs-before-join](https://conversejs.org/docs/html/configuration.html#muc-show-logs-before-join)
+_ New config option [muc_mention_autocomplete_filter](https://conversejs.org/docs/html/configuration.html#muc_mention_autocomplete_filter)
+_ New config option [muc_mention_autocomplete_show_avatar](https://conversejs.org/docs/html/configuration.html#muc_mention_autocomplete_show_avatar)
 
 - #129: Add support for XEP-0156: Disovering Alternative XMPP Connection Methods. Only XML is supported for now.
 - #1105: Preliminary support for storing persistent data in IndexedDB instead of localStorage

+ 26 - 0
sass/_chatrooms.scss

@@ -316,6 +316,18 @@
             }
         }
 
+        .empty-history-feedback {
+            position: relative;
+            height: 100%;
+            color: var(--text-color-lighten-15-percent);
+            span {
+                width: 100%;
+                text-align: center;
+                position: absolute;
+                margin-top: 50%;
+            }
+        }
+
         .muc-bottom-panel {
             border-top: var(--message-input-border-top);
             height: 3em;
@@ -324,6 +336,20 @@
             font-size: var(--font-size-small);
             background-color: var(--chatroom-head-color);
             color: white;
+
+            &.muc-bottom-panel--nickname {
+                padding: 0;
+                height: 16em;
+
+                .chatroom-form-container {
+                    border-radius: 0 !important;
+
+                    .chatroom-form {
+                        padding-top: 2em;
+                        padding-bottom: 0;
+                    }
+                }
+            }
         }
 
         .sendXMPPMessage {

+ 1 - 1
spec/mam.js

@@ -196,7 +196,7 @@
                     </iq>`);
                 _converse.connection._dataRecv(test_utils.createRequest(result));
                 await u.waitUntil(() => view.model.messages.length === 5);
-                expect(view.model.fetchArchivedMessages.calls.count()).toBe(3);
+                expect(view.model.fetchArchivedMessages.calls.count()).toBe(5);
                 const msg_els = view.content.querySelectorAll('.chat-msg__text');
                 expect(Array.from(msg_els).map(e => e.textContent).join(' ')).toBe("2nd Message 3rd Message 4th Message 5th Message 6th Message");
                 done();

+ 2 - 2
spec/muc.js

@@ -1547,7 +1547,7 @@
                 expect(presencebroadcast.length).toBe(1);
                 presencebroadcast[0].value = ['moderator'];
 
-                view.el.querySelector('input[type="submit"]').click();
+                view.el.querySelector('.chatroom-form input[type="submit"]').click();
 
                 const sent_stanza = sent_IQ.nodeTree;
                 expect(sent_stanza.querySelector('field[var="muc#roomconfig_membersonly"] value').textContent.trim()).toBe('1');
@@ -2578,7 +2578,7 @@
                 expect(el.textContent.trim()).toBe("Configuration for room@conference.example.org");
                 sizzle('[name="muc#roomconfig_membersonly"]', chatroomview.el).pop().click();
                 sizzle('[name="muc#roomconfig_roomname"]', chatroomview.el).pop().value = "New room name"
-                chatroomview.el.querySelector('.btn-primary').click();
+                chatroomview.el.querySelector('.chatroom-form input[type="submit"]').click();
 
                 iq = await u.waitUntil(() => _.filter(IQs, iq => u.matchesSelector(iq, `iq[to="${jid}"][type="set"]`)).pop());
                 const result = $iq({

+ 1 - 1
spec/muc_messages.js

@@ -979,7 +979,7 @@
                 await u.waitUntil(() => view.el.querySelector('.chat-msg__text').textContent ===
                     'hello z3r0 gibson sw0rdf1sh, how are you?', 500);
 
-                const correction = _converse.connection.send.calls.all()[2].args[0];
+                const correction = _converse.connection.send.calls.all()[3].args[0];
                 expect(correction.toLocaleString())
                     .toBe(`<message from="romeo@montague.lit/orchard" id="${correction.nodeTree.getAttribute("id")}" `+
                             `to="lounge@montague.lit" type="groupchat" `+

+ 131 - 131
src/converse-muc-views.js

@@ -27,7 +27,7 @@ import tpl_chatroom_features from "templates/chatroom_features.html";
 import tpl_chatroom_form from "templates/chatroom_form.html";
 import tpl_chatroom_head from "templates/chatroom_head.html";
 import tpl_chatroom_invite from "templates/chatroom_invite.html";
-import tpl_chatroom_nickname_form_modal from "templates/chatroom_nickname_form_modal.html";
+import tpl_chatroom_nickname_form from "templates/chatroom_nickname_form.html";
 import tpl_chatroom_password_form from "templates/chatroom_password_form.html";
 import tpl_chatroom_sidebar from "templates/chatroom_sidebar.html";
 import tpl_info from "templates/info.html";
@@ -636,18 +636,20 @@ converse.plugins.add('converse-muc-views', {
                 'click .configure-chatroom-button': 'getAndRenderConfigurationForm',
                 'click .hide-occupants': 'hideOccupants',
                 'click .new-msgs-indicator': 'viewUnreadMessages',
-                'click .occupant-nick': 'onOccupantClicked',
+                // Arrow functions don't work here because you can't bind a different `this` param to them.
+                'click .occupant-nick': function (ev) {this.insertIntoTextArea(ev.target.textContent) },
                 'click .send-button': 'onFormSubmitted',
                 'click .show-room-details-modal': 'showRoomDetailsModal',
                 'click .toggle-call': 'toggleCall',
                 'click .toggle-occupants': 'toggleOccupants',
                 'click .upload-file': 'toggleFileUpload',
+                'dragover .chat-textarea': 'onDragOver',
+                'drop .chat-textarea': 'onDrop',
+                'input .chat-textarea': 'inputChanged',
                 'keydown .chat-textarea': 'onKeyDown',
                 'keyup .chat-textarea': 'onKeyUp',
                 'paste .chat-textarea': 'onPaste',
-                'input .chat-textarea': 'inputChanged',
-                'dragover .chat-textarea': 'onDragOver',
-                'drop .chat-textarea': 'onDrop',
+                'submit .muc-nickname-form': 'submitNickname'
             },
 
             initialize () {
@@ -696,8 +698,8 @@ converse.plugins.add('converse-muc-views', {
                 this.renderHeading();
                 this.renderChatArea();
                 this.renderBottomPanel();
-                if (this.model.get('connection_status') !== converse.ROOMSTATUS.ENTERED) {
-                    this.showSpinner();
+                if (!_converse.muc_show_logs_before_join) {
+                    this.model.get('connection_status') !== converse.ROOMSTATUS.ENTERED && this.showSpinner();
                 }
                 if (!this.model.get('hidden')) {
                     this.show();
@@ -716,9 +718,11 @@ converse.plugins.add('converse-muc-views', {
 
             renderBottomPanel () {
                 const container = this.el.querySelector('.bottom-panel');
-                const can_edit = !(this.model.features.get('moderated') && this.model.getOwnRole() === 'visitor');
-                container.innerHTML = tpl_chatroom_bottom_panel({__, can_edit});
-                if (can_edit) {
+                const entered = this.model.get('connection_status') === converse.ROOMSTATUS.ENTERED;
+                const can_edit = entered && !(this.model.features.get('moderated') && this.model.getOwnRole() === 'visitor');
+                const nickname = this.model.get('nickname');
+                container.innerHTML = tpl_chatroom_bottom_panel({__, can_edit, entered, nickname});
+                if (entered && can_edit) {
                     this.renderMessageForm();
                     this.initMentionAutoComplete();
                 }
@@ -730,7 +734,11 @@ converse.plugins.add('converse-muc-views', {
                     const container_el = this.el.querySelector('.chatroom-body');
                     container_el.insertAdjacentHTML(
                         'beforeend',
-                        tpl_chatarea({'show_send_button': _converse.show_send_button})
+                        tpl_chatarea({
+                            __,
+                            'muc_show_logs_before_join': _converse.muc_show_logs_before_join,
+                            'show_send_button': _converse.show_send_button
+                        })
                     );
                     this.content = this.el.querySelector('.chat-content');
                 }
@@ -799,6 +807,21 @@ converse.plugins.add('converse-muc-views', {
                 this.mention_auto_complete.on('suggestion-box-selectcomplete', () => (this.auto_completing = false));
             },
 
+            /**
+             * Get the nickname value from the form and then join the groupchat with it.
+             * @private
+             * @method _converse.ChatRoomView#submitNickname
+             * @param { Event }
+             */
+            submitNickname (ev) {
+                ev.preventDefault();
+                const nick = ev.target.nick.value.trim();
+                if (nick) {
+                    this.model.join(nick);
+                    this.model.set({'nickname': nick});
+                }
+            },
+
             onKeyDown (ev) {
                 if (this.mention_auto_complete.onKeyDown(ev)) {
                     return;
@@ -997,9 +1020,12 @@ converse.plugins.add('converse-muc-views', {
                 }
             },
 
+            /**
+             * Returns the groupchat heading HTML to be rendered.
+             * @private
+             * @method _converse.ChatRoomView#generateHeadingHTML
+             */
             generateHeadingHTML () {
-                /* Returns the heading HTML to be rendered.
-                 */
                 return tpl_chatroom_head(
                     Object.assign(this.model.toJSON(), {
                         'isOwner': this.model.getOwnAffiliation() === 'owner',
@@ -1028,7 +1054,7 @@ converse.plugins.add('converse-muc-views', {
             onConnectionStatusChanged () {
                 const conn_status = this.model.get('connection_status');
                 if (conn_status === converse.ROOMSTATUS.NICKNAME_REQUIRED) {
-                    this.renderNicknameButton();
+                    this.renderNicknameForm();
                 } else if (conn_status === converse.ROOMSTATUS.PASSWORD_REQUIRED) {
                     this.renderPasswordForm();
                 } else if (conn_status === converse.ROOMSTATUS.CONNECTING) {
@@ -1083,10 +1109,13 @@ converse.plugins.add('converse-muc-views', {
                 }
             },
 
+            /**
+             * Show or hide the right sidebar containing the chat
+             * occupants (and the invite widget).
+             * @private
+             * @method _converse.ChatRoomView#hideOccupants
+             */
             hideOccupants (ev) {
-                /* Show or hide the right sidebar containing the chat
-                 * occupants (and the invite widget).
-                 */
                 if (ev) {
                     ev.preventDefault();
                     ev.stopPropagation();
@@ -1095,10 +1124,13 @@ converse.plugins.add('converse-muc-views', {
                 this.scrollDown();
             },
 
+            /**
+             * Show or hide the right sidebar containing the chat
+             * occupants (and the invite widget).
+             * @private
+             * @method _converse.ChatRoomView#toggleOccupants
+             */
             toggleOccupants (ev) {
-                /* Show or hide the right sidebar containing the chat
-                 * occupants (and the invite widget).
-                 */
                 if (ev) {
                     ev.preventDefault();
                     ev.stopPropagation();
@@ -1107,13 +1139,6 @@ converse.plugins.add('converse-muc-views', {
                 this.scrollDown();
             },
 
-            onOccupantClicked (ev) {
-                /* When an occupant is clicked, insert their nickname into
-                 * the chat textarea input.
-                 */
-                this.insertIntoTextArea(ev.target.textContent);
-            },
-
             verifyRoles (roles, occupant, show_error=true) {
                 if (!Array.isArray(roles)) {
                     throw new TypeError('roles must be an Array');
@@ -1436,6 +1461,34 @@ converse.plugins.add('converse-muc-views', {
                 u.showElement(this.config_form.el);
             },
 
+            /**
+             * Renders a form which allows the user to choose theirnickname.
+             * @private
+             * @method _converse.ChatRoomView#renderNicknameForm
+             */
+            renderNicknameForm () {
+                const heading = _converse.muc_show_logs_before_join ?
+                    __('Choose a nickname to enter') :
+                    __('Please choose your nickname');
+
+                const html = tpl_chatroom_nickname_form({
+                    heading,
+                    'label_nickname': __('Nickname'),
+                    'label_join': __('Enter groupchat'),
+                    'nickname': this.model.get('nickname')
+                });
+                if (_converse.muc_show_logs_before_join) {
+                    const container = this.el.querySelector('.muc-bottom-panel');
+                    container.innerHTML = html;
+                    u.addClass('muc-bottom-panel--nickname', container);
+                } else {
+                    this.hideChatRoomContents();
+                    const container = this.el.querySelector('.chatroom-body');
+                    container.insertAdjacentHTML('beforeend', html);
+                }
+                u.safeSave(this.model, {'connection_status': converse.ROOMSTATUS.NICKNAME_REQUIRED});
+            },
+
             closeForm () {
                 /* Remove the configuration form without submitting and
                  * return to the chat view.
@@ -1444,22 +1497,21 @@ converse.plugins.add('converse-muc-views', {
                 this.renderAfterTransition();
             },
 
+            /**
+             * Start the process of configuring a groupchat, either by
+             * rendering a configuration form, or by auto-configuring
+             * based on the "roomconfig" data stored on the
+             * {@link _converse.ChatRoom}.
+             * Stores the new configuration on the {@link _converse.ChatRoom}
+             * once completed.
+             * @private
+             * @method _converse.ChatRoomView#getAndRenderConfigurationForm
+             * @param { Event } ev - DOM event that might be passed in if this
+             *   method is called due to a user action. In this
+             *   case, auto-configure won't happen, regardless of
+             *   the settings.
+             */
             getAndRenderConfigurationForm () {
-                /* Start the process of configuring a groupchat, either by
-                 * rendering a configuration form, or by auto-configuring
-                 * based on the "roomconfig" data stored on the
-                 * Backbone.Model.
-                 *
-                 * Stores the new configuration on the Backbone.Model once
-                 * completed.
-                 *
-                 * Paremeters:
-                 *  (Event) ev: DOM event that might be passed in if this
-                 *      method is called due to a user action. In this
-                 *      case, auto-configure won't happen, regardless of
-                 *      the settings.
-                 */
-
                 if (!this.config_form || !u.isVisible(this.config_form.el)) {
                     this.showSpinner();
                     this.model.fetchRoomConfiguration()
@@ -1471,35 +1523,10 @@ converse.plugins.add('converse-muc-views', {
             },
 
             hideChatRoomContents () {
-                return;
-            },
-
-            renderNicknameButton () {
-                this.el.querySelector('.setNicknameButtonForm').classList.remove('hidden');
-                this.el.querySelector('.sendXMPPMessage').classList.add('hidden');
-                this.el.querySelector('.setNicknameButtonForm').addEventListener('submit', this.renderNicknameModal.bind(this), false);
-            },
-
-            renderNicknameModal (ev) {
-                /* Render a button which allows the user to get a modal to set their nickname.
-                 */
-                ev.preventDefault();
-                const message = this.model.get('nickname_validation_message');
-                this.model.save('nickname_validation_message', undefined);
-                if (this.nickname_form_modal === undefined) {
-                    this.nickname_form_modal = new _converse.NicknameFormModal({
-                        //'model': new Backbone.Model({'validation_message': message}),
-                        'model': this.model,
-                        'chatroomview': this,
-                    });
-                    const container_el = this.el.querySelector('.chatroom-body');
-                    container_el.insertAdjacentElement('beforeend', this.nickname_form_modal.el);
-                } else {
-                    this.nickname_form_modal.model.set('validation_message', message);
+                const container_el = this.el.querySelector('.chatroom-body');
+                if (container_el !== null) {
+                    [].forEach.call(container_el.children, child => child.classList.add('hidden'));
                 }
-                this.nickname_form_modal.show(ev);
-                console.log(this.nickname_form_modal);
-                u.safeSave(this.model, {'connection_status': converse.ROOMSTATUS.NICKNAME_REQUIRED});
             },
 
             renderPasswordForm () {
@@ -1598,7 +1625,19 @@ converse.plugins.add('converse-muc-views', {
                 }
             },
 
+            insertMessage (view) {
+                if (_converse.muc_show_logs_before_join &&
+                        this.content.firstElementChild.matches('.empty-history-feedback')) {
+                    this.content.removeChild(this.content.firstElementChild);
+                }
+                return _converse.ChatBoxView.prototype.insertMessage.call(this, view);
+            },
+
             insertNotification (message) {
+                if (_converse.muc_show_logs_before_join &&
+                        this.content.firstElementChild.matches('.empty-history-feedback')) {
+                    this.content.removeChild(this.content.firstElementChild);
+                }
                 this.content.insertAdjacentHTML(
                     'beforeend',
                     tpl_info({
@@ -1777,13 +1816,16 @@ converse.plugins.add('converse-muc-views', {
                 this.scrollDown();
             },
 
+            /**
+             * Rerender the groupchat after some kind of transition. For
+             * example after the spinner has been removed or after a
+             * form has been submitted and removed.
+             * @private
+             * @method _converse.ChatRoomView#renderAfterTransition
+             */
             renderAfterTransition () {
-                /* Rerender the groupchat after some kind of transition. For
-                 * example after the spinner has been removed or after a
-                 * form has been submitted and removed.
-                 */
                 if (this.model.get('connection_status') == converse.ROOMSTATUS.NICKNAME_REQUIRED) {
-                    this.renderNicknameButton();
+                    this.renderNicknameForm();
                 } else if (this.model.get('connection_status') == converse.ROOMSTATUS.PASSWORD_REQUIRED) {
                     this.renderPasswordForm();
                 } else if (this.model.get('connection_status') == converse.ROOMSTATUS.ENTERED) {
@@ -1801,11 +1843,14 @@ converse.plugins.add('converse-muc-views', {
                 container_el.insertAdjacentHTML('afterbegin', tpl_spinner());
             },
 
+            /**
+             * Check if the spinner is being shown and if so, hide it.
+             * Also make sure then that the chat area and occupants
+             * list are both visible.
+             * @private
+             * @method _converse.ChatRoomView#hideSpinner
+             */
             hideSpinner () {
-                /* Check if the spinner is being shown and if so, hide it.
-                 * Also make sure then that the chat area and occupants
-                 * list are both visible.
-                 */
                 const spinner = this.el.querySelector('.spinner');
                 if (spinner !== null) {
                     u.removeElement(spinner);
@@ -1845,9 +1890,13 @@ converse.plugins.add('converse-muc-views', {
         });
 
 
+        /**
+         * Backbone.NativeView which renders MUC section of the control box.
+         * @class
+         * @namespace _converse.RoomsPanel
+         * @memberOf _converse
+         */
         _converse.RoomsPanel = Backbone.NativeView.extend({
-            /* Backbone.NativeView which renders MUC section of the control box.
-             */
             tagName: 'div',
             className: 'controlbox-section',
             id: 'chatrooms',
@@ -1884,7 +1933,7 @@ converse.plugins.add('converse-muc-views', {
         _converse.MUCConfigForm = Backbone.VDOMView.extend({
             className: 'muc-config-form',
             events: {
-                'submit form': 'submitConfigForm',
+                'submit .chatroom-form': 'submitConfigForm',
                 'click .button-cancel': 'closeConfigForm'
             },
 
@@ -1961,55 +2010,6 @@ converse.plugins.add('converse-muc-views', {
         });
 
 
-        _converse.NicknameFormModal = _converse.BootstrapModal.extend({
-
-            events: {
-                'submit form': 'submitNickname',
-            },
-
-            initialize (attrs) {
-                _converse.BootstrapModal.prototype.initialize.apply(this, arguments);
-                this.chatroomview = attrs.chatroomview;
-                this.listenTo(this.model, 'change:validation_message', this.render);
-                this.render();
-            },
-
-            toHTML () {
-                const err_msg = this.model.get('validation_message');
-                return tpl_chatroom_nickname_form_modal({
-                    '__': __,
-                    'heading': __('Please choose your nickname'),
-                    'label_nickname': __('Nickname'),
-                    'label_join': __('Enter groupchat'),
-                    'error_class': err_msg ? 'error' : '',
-                    'validation_message': err_msg,
-                    'nickname': this.model.get('nickname')
-                });
-            },
-
-            submitNickname (ev) {
-                /* Get the nickname value from the form and then join the
-                 * groupchat with it.
-                 */
-                ev.preventDefault();
-                const nick_el = ev.target.nick;
-                const nick = nick_el.value.trim();
-                if (nick) {
-                    this.chatroomview.model.join(nick);
-                    this.model.set({
-                        'validation_message': null,
-                        'nickname': nick
-                    });
-                } else {
-                    return this.model.set({
-                        'validation_message': __('You need to provide a nickname')
-                    });
-                }
-                this.modal.hide();
-            }
-        });
-
-
         _converse.ChatRoomOccupantView = Backbone.VDOMView.extend({
             tagName: 'li',
             initialize () {

+ 10 - 9
src/headless/converse-mam.js

@@ -58,6 +58,7 @@ converse.plugins.add('converse-mam', {
             /**
              * Fetches messages that might have been archived *after*
              * the last archived message in our local cache.
+             * @private
              */
             fetchNewestMessages () {
                 if (this.disable_mam) {
@@ -165,8 +166,9 @@ converse.plugins.add('converse-mam', {
 
         Object.assign(_converse.ChatRoom.prototype, {
             fetchArchivedMessagesIfNecessary () {
-                if (this.get('connection_status') !== converse.ROOMSTATUS.ENTERED ||
-                        !this.get('mam_enabled') ||
+                const conn_status = this.get('connection_status');
+                if ((!_converse.muc_show_logs_before_join && conn_status !== converse.ROOMSTATUS.ENTERED) ||
+                        !this.features.get('mam_enabled') ||
                         this.get('mam_initialized')) {
                     return;
                 }
@@ -177,7 +179,7 @@ converse.plugins.add('converse-mam', {
 
 
         _converse.onMAMError = function (iq) {
-            if (iq.querySelectorAll('feature-not-implemented').length) {
+            if (iq && iq.querySelectorAll('feature-not-implemented').length) {
                 log.warn("Message Archive Management (XEP-0313) not supported by this server");
             } else {
                 log.error("An error occured while trying to set archiving preferences.");
@@ -232,7 +234,11 @@ converse.plugins.add('converse-mam', {
 
         _converse.api.listen.on('addClientFeatures', () => _converse.api.disco.own.features.add(Strophe.NS.MAM));
         _converse.api.listen.on('serviceDiscovered', getMAMPrefsFromFeature);
-        _converse.api.listen.on('enteredNewRoom', chat => chat.fetchNewestMessages());
+        _converse.api.listen.on('enteredNewRoom', room => room.features.get('mam_enabled') && room.fetchNewestMessages());
+        _converse.api.listen.on('chatRoomOpened', (view) => {
+            view.listenTo(view.model, 'change:connection_status', () => view.model.fetchArchivedMessagesIfNecessary());
+        });
+
         _converse.api.listen.on('chatReconnected', chat => {
             // XXX: For MUCs, we listen to enteredNewRoom instead
             if (chat.get('type') === _converse.PRIVATE_CHAT_TYPE) {
@@ -250,11 +256,6 @@ converse.plugins.add('converse-mam', {
                 chat.fetchNewestMessages();
             }
         });
-
-        _converse.api.listen.on('chatRoomOpened', (room) => {
-            room.on('change:mam_enabled', room.fetchArchivedMessagesIfNecessary, room);
-            room.on('change:connection_status', room.fetchArchivedMessagesIfNecessary, room);
-        });
         /************************ END Event Handlers **************************/
 
 

+ 2 - 1
src/headless/converse-muc.js

@@ -129,7 +129,8 @@ converse.plugins.add('converse-muc', {
             'muc_fetch_members': true,
             'muc_history_max_stanzas': undefined,
             'muc_instant_rooms': true,
-            'muc_nickname_from_jid': false
+            'muc_nickname_from_jid': false,
+            'muc_show_logs_before_join': false
         });
         _converse.api.promises.add(['roomsAutoJoined']);
 

+ 5 - 1
src/templates/chatarea.html

@@ -1,4 +1,8 @@
 <div class="chat-area col">
-    <div class="chat-content {[ if (o.show_send_button) { ]}chat-content-sendbutton{[ } ]}" aria-live="polite"></div>
+    <div class="chat-content {[ if (o.show_send_button) { ]}chat-content-sendbutton{[ } ]}" aria-live="polite">
+        {[ if (o.muc_show_logs_before_join) { ]}
+            <div class="empty-history-feedback"><span>{{{o.__('No message history available.')}}}</span></div>
+        {[ } ]}
+    </div>
     <div class="bottom-panel"></div>
 </div>

+ 8 - 4
src/templates/chatroom_bottom_panel.html

@@ -1,6 +1,10 @@
-{[ if (o.can_edit) { ]}
-<div class="emoji-picker__container dropup"></div>
-<div class="message-form-container">
+{[ if (o.entered) { ]}
+    {[ if (o.can_edit) { ]}
+        <div class="emoji-picker__container dropup"></div>
+        <div class="message-form-container">
+    {[ } else { ]}
+        <div class="muc-bottom-panel">{{{o.__("You're not allowed to send messages in this room")}}}</div>
+    {[ } ]}
 {[ } else { ]}
-<div class="muc-bottom-panel">{{{o.__("You're not allowed to send messages in this room")}}}</div>
+    <div class="muc-bottom-panel"></div>
 {[ } ]}

+ 13 - 0
src/templates/chatroom_nickname_form.html

@@ -0,0 +1,13 @@
+<div class="chatroom-form-container muc-nickname-form">
+    <form class="converse-form chatroom-form converse-centered-form">
+        <fieldset class="form-group">
+            <label>{{{o.heading}}}</label>
+            <p class="validation-message">{{{o.validation_message}}}</p>
+            <input type="text" required="required" name="nick" value="{{{o.nickname}}}"
+                   class="form-control {{o.error_class}}" placeholder="{{{o.label_nickname}}}"/>
+        </fieldset>
+        <fieldset class="form-group">
+            <input type="submit" class="btn btn-primary" name="join" value="{{{o.label_join}}}"/>
+        </fieldset>
+    </form>
+</div>

+ 0 - 26
src/templates/chatroom_nickname_form_modal.html

@@ -1,26 +0,0 @@
-<div class="modal" id="ask-nickname-modal" tabindex="-1" role="dialog" aria-labelledby="ask-nickname-modal-label" aria-hidden="true">
-    <div class="modal-dialog" role="document">
-        <div class="modal-content">
-            <div class="modal-header">
-                <h5 class="modal-title"
-                    id="ask-nickname-modal-label">{{{o.heading}}}</h5>
-                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
-                    <span aria-hidden="true">×</span>
-                </button>
-            </div>
-            <div class="modal-body">
-                <form class="converse-form chatroom-form converse-centered-form">
-                    <fieldset class="form-group">
-                        <label>{{{o.__('Nickname:')}}}</label>
-                        <p class="validation-message">{{{o.validation_message}}}</p>
-                        <input type="text" required="required" name="nick" value="{{{o.nickname}}}"
-                               class="form-control {{o.error_class}}" placeholder="{{{o.label_nickname}}}"/>
-                    </fieldset>
-                    <fieldset class="form-group">
-                        <input type="submit" class="btn btn-primary" name="join" value="{{{o.label_join}}}"/>
-                    </fieldset>
-                </form>
-            </div>
-        </div>
-    </div>
-</div>

+ 2 - 1
webpack.html

@@ -19,7 +19,7 @@
     converse.initialize({
         auto_away: 300,
         auto_register_muc_nickname: true,
-        debug: true,
+        loglevel: 'debug',
         enable_smacks: true,
         i18n: 'en',
         message_archiving: 'always',
@@ -27,6 +27,7 @@
         muc_respect_autojoin: true,
         view_mode: 'fullscreen',
         websocket_url: 'ws://chat.example.org:5380/xmpp-websocket',
+        muc_show_logs_before_join: true,
         whitelisted_plugins: ['converse-debug'],
     });
 </script>