瀏覽代碼

muc-views: Remove features section...

and replace with button to open invite modal
JC Brand 5 年之前
父節點
當前提交
30d08d2bfe
共有 5 個文件被更改,包括 94 次插入116 次删除
  1. 4 3
      sass/_chatrooms.scss
  2. 16 0
      sass/_core.scss
  3. 61 43
      spec/muc.js
  4. 1 0
      src/converse-muc-views.js
  5. 12 70
      src/templates/muc_sidebar.js

+ 4 - 3
sass/_chatrooms.scss

@@ -181,9 +181,10 @@
                         margin-bottom: 0.5em;
                         display: flex;
                         flex-direction: row;
-                        .fa-user-plus {
-                            margin-top: 0.2em;
-                        }
+                    }
+
+                    .fa-user-plus {
+                        margin-right: 0.5em;
                     }
 
                     .occupants-heading {

+ 16 - 0
sass/_core.scss

@@ -541,6 +541,22 @@ body.converse-fullscreen {
         }
     }
 
+    .btn-circle {
+        width: 32px;
+        height: 32px;
+        text-align: center;
+        padding: 0.5em 0;
+        font-size: var(--font-size-small);
+        line-height: 1.428571429;
+        border-radius: 50%;
+    }
+
+    .btn {
+      &.fa {
+        color: white !important;
+      }
+    }
+
     .badge-groupchat {
         background-color: var(--chatroom-badge-color);
         border-color: transparent;

+ 61 - 43
spec/muc.js

@@ -1944,16 +1944,16 @@
                 expect(view.model.getOwnAffiliation()).toBe('owner');
                 expect(view.model.features.get('open')).toBe(false);
 
-                expect(view.el.querySelector('.occupants-header .fa-user-plus')).not.toBe(null);
+                expect(view.el.querySelector('.open-invite-modal')).not.toBe(null);
 
                 // Members can't invite if the room isn't open
                 view.model.getOwnOccupant().set('affiliation', 'member');
-                await u.waitUntil(() => view.el.querySelector('.occupants-header .fa-user-plus') === null);
+                await u.waitUntil(() => view.el.querySelector('.open-invite-modal') === null);
 
                 view.model.features.set('open', 'true');
-                await u.waitUntil(() => view.el.querySelector('.occupants-header .fa-user-plus'));
+                await u.waitUntil(() => view.el.querySelector('.open-invite-modal'));
 
-                view.el.querySelector('.occupants-header .fa-user-plus').click();
+                view.el.querySelector('.open-invite-modal').click();
                 const modal = view.sidebar_view.muc_invite_modal;
                 await u.waitUntil(() => u.isVisible(modal.el), 1000)
 
@@ -2506,26 +2506,38 @@
                 ];
                 await test_utils.openAndEnterChatRoom(_converse, 'room@conference.example.org', 'romeo', features);
                 const jid = 'room@conference.example.org';
-                const chatroomview = _converse.chatboxviews.get(jid);
-                let features_list = chatroomview.el.querySelector('.features-list');
+                const view = _converse.chatboxviews.get(jid);
+
+                const info_el = view.el.querySelector(".show-room-details-modal");
+                info_el.click();
+                const  modal = view.model.room_details_modal;
+                await u.waitUntil(() => u.isVisible(modal.el), 1000);
+
+                let features_list = modal.el.querySelector('.features-list');
                 let features_shown = features_list.textContent.split('\n').map(s => s.trim()).filter(s => s);
-                expect(_.difference(["Password protected", "Open", "Temporary", "Not anonymous", "Not moderated"], features_shown).length).toBe(0);
-                expect(chatroomview.model.features.get('hidden')).toBe(false);
-                expect(chatroomview.model.features.get('mam_enabled')).toBe(false);
-                expect(chatroomview.model.features.get('membersonly')).toBe(false);
-                expect(chatroomview.model.features.get('moderated')).toBe(false);
-                expect(chatroomview.model.features.get('nonanonymous')).toBe(true);
-                expect(chatroomview.model.features.get('open')).toBe(true);
-                expect(chatroomview.model.features.get('passwordprotected')).toBe(true);
-                expect(chatroomview.model.features.get('persistent')).toBe(false);
-                expect(chatroomview.model.features.get('publicroom')).toBe(true);
-                expect(chatroomview.model.features.get('semianonymous')).toBe(false);
-                expect(chatroomview.model.features.get('temporary')).toBe(true);
-                expect(chatroomview.model.features.get('unmoderated')).toBe(true);
-                expect(chatroomview.model.features.get('unsecured')).toBe(false);
-                expect(chatroomview.el.querySelector('.chatbox-title__text').textContent.trim()).toBe('Room');
-
-                chatroomview.el.querySelector('.configure-chatroom-button').click();
+
+                expect(features_shown.join(' ')).toBe(
+                    'Password protected - This groupchat requires a password before entry '+
+                    'Open - Anyone can join this groupchat '+
+                    'Temporary - This groupchat will disappear once the last person leaves '+
+                    'Not anonymous - All other groupchat participants can see your XMPP address '+
+                    'Not moderated - Participants entering this groupchat can write right away');
+                expect(view.model.features.get('hidden')).toBe(false);
+                expect(view.model.features.get('mam_enabled')).toBe(false);
+                expect(view.model.features.get('membersonly')).toBe(false);
+                expect(view.model.features.get('moderated')).toBe(false);
+                expect(view.model.features.get('nonanonymous')).toBe(true);
+                expect(view.model.features.get('open')).toBe(true);
+                expect(view.model.features.get('passwordprotected')).toBe(true);
+                expect(view.model.features.get('persistent')).toBe(false);
+                expect(view.model.features.get('publicroom')).toBe(true);
+                expect(view.model.features.get('semianonymous')).toBe(false);
+                expect(view.model.features.get('temporary')).toBe(true);
+                expect(view.model.features.get('unmoderated')).toBe(true);
+                expect(view.model.features.get('unsecured')).toBe(false);
+                expect(view.el.querySelector('.chatbox-title__text').textContent.trim()).toBe('Room');
+
+                view.el.querySelector('.configure-chatroom-button').click();
 
                 const IQs = _converse.connection.IQ_stanzas;
                 let iq = await u.waitUntil(() => _.filter(
@@ -2602,9 +2614,9 @@
                 _converse.connection._dataRecv(test_utils.createRequest(response_el));
                 const el = await u.waitUntil(() => document.querySelector('.chatroom-form legend'));
                 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('.chatroom-form input[type="submit"]').click();
+                sizzle('[name="muc#roomconfig_membersonly"]', view.el).pop().click();
+                sizzle('[name="muc#roomconfig_roomname"]', view.el).pop().value = "New room name"
+                view.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({
@@ -2656,24 +2668,30 @@
 
                 _converse.connection._dataRecv(test_utils.createRequest(features_stanza));
 
-                await u.waitUntil(() => new Promise(success => chatroomview.model.features.on('change', success)));
-                features_list = chatroomview.el.querySelector('.features-list');
+                await u.waitUntil(() => new Promise(success => view.model.features.on('change', success)));
+                features_list = modal.el.querySelector('.features-list');
                 features_shown = features_list.textContent.split('\n').map(s => s.trim()).filter(s => s);
-                expect(_.difference(["Password protected", "Hidden", "Members only", "Temporary", "Not anonymous", "Not moderated"], features_shown).length).toBe(0);
-                expect(chatroomview.model.features.get('hidden')).toBe(true);
-                expect(chatroomview.model.features.get('mam_enabled')).toBe(false);
-                expect(chatroomview.model.features.get('membersonly')).toBe(true);
-                expect(chatroomview.model.features.get('moderated')).toBe(false);
-                expect(chatroomview.model.features.get('nonanonymous')).toBe(true);
-                expect(chatroomview.model.features.get('open')).toBe(false);
-                expect(chatroomview.model.features.get('passwordprotected')).toBe(true);
-                expect(chatroomview.model.features.get('persistent')).toBe(false);
-                expect(chatroomview.model.features.get('publicroom')).toBe(false);
-                expect(chatroomview.model.features.get('semianonymous')).toBe(false);
-                expect(chatroomview.model.features.get('temporary')).toBe(true);
-                expect(chatroomview.model.features.get('unmoderated')).toBe(true);
-                expect(chatroomview.model.features.get('unsecured')).toBe(false);
-                expect(chatroomview.el.querySelector('.chatbox-title__text').textContent.trim()).toBe('New room name');
+                expect(features_shown.join(' ')).toBe(
+                    'Password protected - This groupchat requires a password before entry '+
+                    'Hidden - This groupchat is not publicly searchable '+
+                    'Members only - This groupchat is restricted to members only '+
+                    'Temporary - This groupchat will disappear once the last person leaves '+
+                    'Not anonymous - All other groupchat participants can see your XMPP address '+
+                    'Not moderated - Participants entering this groupchat can write right away');
+                expect(view.model.features.get('hidden')).toBe(true);
+                expect(view.model.features.get('mam_enabled')).toBe(false);
+                expect(view.model.features.get('membersonly')).toBe(true);
+                expect(view.model.features.get('moderated')).toBe(false);
+                expect(view.model.features.get('nonanonymous')).toBe(true);
+                expect(view.model.features.get('open')).toBe(false);
+                expect(view.model.features.get('passwordprotected')).toBe(true);
+                expect(view.model.features.get('persistent')).toBe(false);
+                expect(view.model.features.get('publicroom')).toBe(false);
+                expect(view.model.features.get('semianonymous')).toBe(false);
+                expect(view.model.features.get('temporary')).toBe(true);
+                expect(view.model.features.get('unmoderated')).toBe(true);
+                expect(view.model.features.get('unsecured')).toBe(false);
+                expect(view.el.querySelector('.chatbox-title__text').textContent.trim()).toBe('New room name');
                 done();
             }));
 

+ 1 - 0
src/converse-muc-views.js

@@ -615,6 +615,7 @@ converse.plugins.add('converse-muc-views', {
             initialize () {
                 _converse.BootstrapModal.prototype.initialize.apply(this, arguments);
                 this.listenTo(this.model, 'change', this.render);
+                this.listenTo(this.model.features, 'change', this.render);
                 this.listenTo(this.model.occupants, 'add', this.render);
                 this.listenTo(this.model.occupants, 'change', this.render);
             },

+ 12 - 70
src/templates/muc_sidebar.js

@@ -1,9 +1,8 @@
 import { html } from "lit-html";
 import { __ } from '@converse/headless/i18n';
-import { pick } from "lodash";
-import converse from "@converse/headless/converse-core";
 import tpl_occupant from "./occupant.js";
 
+
 const PRETTY_CHAT_STATUS = {
     'offline':      'Offline',
     'unavailable':  'Unavailable',
@@ -16,77 +15,21 @@ const PRETTY_CHAT_STATUS = {
 
 const occupant_hint = (occupant) => __('Click to mention %1$s in your message.', occupant.get('nick'))
 
-const i18n_archived = __('Message archiving');
-const i18n_archived_hint = __('Messages are archived on the server');
-const i18n_features = __('Features');
-const i18n_hidden = __('Hidden');
-const i18n_invite_hint = __('Invite people to join this groupchat');
-const i18n_members_only = __('Members only');
-const i18n_members_only_hint = __('this groupchat is restricted to members only');
-const i18n_moderated = __('Moderated');
-const i18n_moderated_hint = __('Participants entering this groupchat need to request permission to write');
-const i18n_no_password = __('No password');
-const i18n_no_password_hint = __('This groupchat does not require a password upon entry');
-const i18n_non_anon_hint = __('All other groupchat participants can see your XMPP address');
-const i18n_not_anon = __('Not anonymous');
-const i18n_not_moderated = __('Not moderated');
-const i18n_not_searchable_hint = __('This groupchat is not publicly searchable');
-const i18n_open = __('Open');
-const i18n_open_hint = __('Anyone can join this groupchat');
+const i18n_invite_hint = __('Invite someone');
 const i18n_participants = __('Participants');
-const i18n_password = __('Password protected')
-const i18n_password_hint = __('This groupchat requires a password before entry');
-const i18n_persistent = __('Persistent');
-const i18n_persistent_hint = __('This groupchat persists even if it\'s unoccupied');
-const i18n_public =  __('Public');
-const i18n_searchable_hint = __('This groupchat is publicly searchable');
-const i18n_semi_anon = __('Semi-anonymous');
-const i18n_semi_anon_hint = __('Only moderators can see your XMPP address');
-const i18n_temporary = __('Temporary');
-const i18n_temporary_hint = __('This groupchat will disappear once the last person leaves');
-const i18n_unmoderated_hint = __('Participants entering this groupchat can write right away');
-
-
-function renderFeatures (o) {
-    const picks = pick(o.features.attributes, converse.ROOM_FEATURES);
-    const iteratee = (a, v) => a || v;
-    if (Object.values(picks).reduce(iteratee)) {
-        return tpl_features(o.features.toJSON());
-    } else {
-        return '';
-    }
-}
 
 
-const tpl_features = (o) => html`
-    <div class="chatroom-features">
-        <p class="occupants-heading">${i18n_features}</p>
-        <ul class="features-list">
-            ${ (o.passwordprotected) ? html`<li class="feature" title="${ i18n_password_hint }"><span class="fa fa-lock"></span>${ i18n_password }</li>` : '' }
-            ${ (o.unsecured) ? html`<li class="feature" title="${ i18n_no_password_hint }"><span class="fa fa-unlock"></span>${ i18n_no_password }</li>` : '' }
-            ${ (o.hidden) ? html`<li class="feature" title="${ i18n_not_searchable_hint }"><span class="fa fa-eye-slash"></span>${ i18n_hidden }</li>` : '' }
-            ${ (o.public_room) ? html`<li class="feature" title="${ i18n_searchable_hint }"><span class="fa fa-eye"></span>${ i18n_public }</li>` : '' }
-            ${ (o.membersonly) ? html`<li class="feature" title="${ i18n_members_only_hint }"><span class="fa fa-address-book"></span>${ i18n_members_only }</li>` : '' }
-            ${ (o.open) ? html`<li class="feature" title="${ i18n_open_hint }"><span class="fa fa-globe"></span>${ i18n_open }</li>` : '' }
-            ${ (o.persistent) ? html`<li class="feature" title="${ i18n_persistent_hint }"><span class="fa fa-save"></span>${ i18n_persistent }</li>` : '' }
-            ${ (o.temporary) ? html`<li class="feature" title="${ i18n_temporary_hint }"><span class="fa fa-snowflake"></span>${ i18n_temporary }</li>` : '' }
-            ${ (o.nonanonymous) ? html`<li class="feature" title="${ i18n_non_anon_hint }"><span class="fa fa-id-card"></span>${ i18n_not_anon }</li>` : '' }
-            ${ (o.semianonymous) ? html`<li class="feature" title="${ i18n_semi_anon_hint }"><span class="fa fa-user-secret"></span>${ i18n_semi_anon }</li>` : '' }
-            ${ (o.moderated) ? html`<li class="feature" title="${ i18n_moderated_hint }"><span class="fa fa-gavel"></span>${ i18n_moderated }</li>` : '' }
-            ${ (o.unmoderated) ? html`<li class="feature" title="${ i18n_unmoderated_hint }"><span class="fa fa-info-circle"></span>${ i18n_not_moderated }</li>` : '' }
-            ${ (o.mam_enabled) ? html`<li class="feature" title="${ i18n_archived_hint }"><span class="fa fa-database"></span>${ i18n_archived }</li>` : '' }
-        </ul>
-    </div>
-`;
-
-const invite_button = (o) => {
+const invite_widget = (o) => {
    if (o.invitesAllowed()) {
         return html`
-            <a class="fa fa-user-plus"
-               title="${i18n_invite_hint}"
-               @click=${o.showInviteModal}
-               data-toggle="modal"
-               data-target="#muc-invite-modal"></a>`;
+           <a class="open-invite-modal"
+              title="${i18n_invite_hint}"
+              data-toggle="modal"
+              data-target="#muc-invite-modal"
+              @click=${o.showInviteModal}>
+            <i class="btn btn-primary btn-circle fa fa-user-plus"></i>
+            ${i18n_invite_hint}
+         </a>`;
    } else {
        return '';
    }
@@ -98,7 +41,6 @@ export default (o) => html`
         <i class="hide-occupants fa fa-times"></i>
         <div class="occupants-header--title">
             <span class="occupants-heading">${i18n_participants}</span>
-            ${ invite_button(o) }
         </div>
     </div>
     <div class="dragresize dragresize-occupants-left"></div>
@@ -113,5 +55,5 @@ export default (o) => html`
                 );
         }) }
     </ul>
-    ${ renderFeatures(o) }
+    ${ invite_widget(o) }
 `;