瀏覽代碼

Move buttons for requesting contacts into dropdown

JC Brand 2 月之前
父節點
當前提交
e84579b2f1

+ 2 - 2
src/plugins/rosterview/contactview.js

@@ -112,8 +112,8 @@ export default class RosterContactView extends ObservableElement {
         const blocking_supported = await api.disco.supports(Strophe.NS.BLOCKING, domain);
 
         const result = await api.confirm(
-            __('Decline contact request'),
-            [__('Are you sure you want to decline this contact request from %1$s?', this.model.getDisplayName())],
+            __('Remove and decline contact request'),
+            [__('Are you sure you want to decline the contact request from %1$s?', this.model.getDisplayName())],
             blocking_supported
                 ? [
                       {

+ 0 - 3
src/plugins/rosterview/styles/roster.scss

@@ -149,9 +149,6 @@
                 .span {
                     display: inline-block;
                 }
-                .decline-xmpp-request {
-                    margin-inline-start: 1em;
-                }
                 &:hover {
                     background-color: var(--highlight-color-hover);
                 }

+ 36 - 21
src/plugins/rosterview/templates/group.js

@@ -1,17 +1,16 @@
-import { html } from "lit";
+import { html } from 'lit';
 import { repeat } from 'lit/directives/repeat.js';
-import { _converse, api, u } from "@converse/headless";
+import { _converse, api, u } from '@converse/headless';
 import 'shared/components/icons.js';
 import { __ } from 'i18n';
 import { toggleGroup } from '../utils.js';
 
 const { isUniView } = u;
 
-
 /**
  * @param {import('@converse/headless/types/plugins/roster/contact').default} contact
  */
-function renderContact (contact) {
+function renderContact(contact) {
     const jid = contact.get('jid');
     const extra_classes = [];
     if (isUniView()) {
@@ -21,9 +20,9 @@ function renderContact (contact) {
         }
     }
     const ask = contact.get('ask');
-    const requesting  = contact.get('requesting');
+    const requesting = contact.get('requesting');
     const subscription = contact.get('subscription');
-    if ((ask === 'subscribe') || (subscription === 'from')) {
+    if (ask === 'subscribe' || subscription === 'from') {
         /* ask === 'subscribe'
          *      Means we have asked to subscribe to them.
          *
@@ -43,23 +42,39 @@ function renderContact (contact) {
         extra_classes.push(subscription);
         extra_classes.push(contact.getStatus());
     }
-    return html`
-        <li class="list-item d-flex controlbox-padded ${extra_classes.join(' ')}" data-status="${contact.getStatus()}">
-            <converse-roster-contact .model=${contact}></converse-roster-contact>
-        </li>`;
+    return html` <li
+        class="list-item d-flex controlbox-padded ${extra_classes.join(' ')}"
+        data-status="${contact.getStatus()}"
+    >
+        <converse-roster-contact .model=${contact}></converse-roster-contact>
+    </li>`;
 }
 
-
 export default (o) => {
     const i18n_title = __('Click to hide these contacts');
     const collapsed = _converse.state.roster.state.get('collapsed_groups');
-    return html`
-        <div class="roster-group" data-group="${o.name}">
-            <a href="#" class="list-toggle group-toggle controlbox-padded" title="${i18n_title}" @click=${ev => toggleGroup(ev, o.name)}>
-                <converse-icon color="var(--chat-color)" size="1em" class="fa ${ (collapsed.includes(o.name)) ? 'fa-caret-right' : 'fa-caret-down' }"></converse-icon> ${o.name}
-            </a>
-            <ul class="items-list roster-group-contacts ${ (collapsed.includes(o.name)) ? 'collapsed' : '' }" data-group="${o.name}">
-                ${ repeat(o.contacts, (c) => c.get('jid'), renderContact) }
-            </ul>
-        </div>`;
-}
+    return html`<div class="roster-group" data-group="${o.name}">
+        <a
+            href="#"
+            class="list-toggle group-toggle controlbox-padded"
+            title="${i18n_title}"
+            @click=${(ev) => toggleGroup(ev, o.name)}
+        >
+            <converse-icon
+                color="var(--chat-color)"
+                size="1em"
+                class="fa ${collapsed.includes(o.name) ? 'fa-caret-right' : 'fa-caret-down'}"
+            ></converse-icon>
+            ${o.name}&nbsp;
+            ${o.contacts[0].get('requesting')
+                ? html` <converse-icon color="var(--chat-color)" size="1.2em" class="fa fa-bell-alt"></converse-icon>`
+                : ``}
+        </a>
+        <ul
+            class="items-list roster-group-contacts ${collapsed.includes(o.name) ? 'collapsed' : ''}"
+            data-group="${o.name}"
+        >
+            ${repeat(o.contacts, (c) => c.get('jid'), renderContact)}
+        </ul>
+    </div>`;
+};

+ 26 - 20
src/plugins/rosterview/templates/requesting_contact.js

@@ -1,6 +1,7 @@
 import { html } from 'lit';
 import { __ } from 'i18n';
 import { getUnreadMsgsDisplay } from 'shared/chat/utils.js';
+import {tplDetailsButton } from './roster_item';
 
 /**
  * @param {import('../contactview').default} el
@@ -9,12 +10,34 @@ export default (el) => {
     const num_unread = getUnreadMsgsDisplay(el.model);
     const jid = el.model.get('jid');
     const display_name = el.model.getDisplayName();
-
     const i18n_accept = __('Click to accept the contact request from %1$s (XMPP address: %2$s)', display_name, jid);
     const i18n_decline = __('Click to decline the contact request from %1$s (XMPP address: %2$s)', display_name, jid);
     const i18n_chat = __('Click to chat with %1$s (XMPP address: %2$s)', display_name, jid);
+    const btns = [
+        html`<a
+                class="dropdown-item accept-xmpp-request"
+                role="button"
+                @click="${(ev) => el.acceptRequest(ev)}"
+                aria-label="${i18n_accept}"
+                title="${i18n_accept}"
+                href="#"
+            >
+            <converse-icon class="fa fa-check" size="1em"></converse-icon>
+            ${__('Accept as contact')}
+        </a>`,
+        tplDetailsButton(el),
+        html`<a class="dropdown-item decline-xmpp-request"
+                role="button"
+                @click="${(ev) => el.declineRequest(ev)}"
+                aria-label="${i18n_decline}"
+                title="${i18n_decline}"
+            >
+            <converse-icon class="fa fa-times" size="1em"></converse-icon>
+            ${__('Remove')}
+        </a>`,
+    ];
 
-    return html` <a
+    return html`<a
             class="list-item-link cbox-list-item open-chat ${num_unread ? 'unread-msgs' : ''}"
             title="${i18n_chat}"
             href="#"
@@ -35,23 +58,6 @@ export default (el) => {
             <span class="contact-name ${num_unread ? 'unread-msgs' : ''}">${display_name}</span>
         </a>
         <span class="contact-actions">
-            <a
-                class="accept-xmpp-request list-item-action list-item-action--visible"
-                @click=${el.acceptRequest}
-                aria-label="${i18n_accept}"
-                title="${i18n_accept}"
-                href="#"
-            >
-                <converse-icon class="fa fa-check" size="1.5em"></converse-icon>
-            </a>
-            <a
-                class="decline-xmpp-request list-item-action list-item-action--visible"
-                @click=${el.declineRequest}
-                aria-label="${i18n_decline}"
-                title="${i18n_decline}"
-                href="#"
-            >
-                <converse-icon class="fa fa-times" size="1.5em"></converse-icon>
-            </a>
+            <converse-dropdown class="btn-group dropstart list-item-action" .items=${btns}></converse-dropdown>
         </span>`;
 };

+ 1 - 2
src/plugins/rosterview/tests/roster.js

@@ -865,7 +865,6 @@ describe("The Contacts Roster", function () {
             pres = $pres({from: 'mercutio@montague.lit/resource'}).c('show', 'away');
             _converse.api.connection.get()._dataRecv(mock.createRequest(pres));
             await u.waitUntil(() => icon_el.getAttribute('color') === 'var(--chat-status-away)');
-                    return
 
             pres = $pres({from: 'mercutio@montague.lit/resource'}).c('show', 'xa');
             _converse.api.connection.get()._dataRecv(mock.createRequest(pres));
@@ -1186,7 +1185,7 @@ describe("The Contacts Roster", function () {
         }));
     });
 
-    describe("Requesting Contacts", function () {
+    fdescribe("Requesting Contacts", function () {
 
         it("can be added to the roster and they will be sorted alphabetically",
             mock.initConverse(

+ 7 - 0
src/shared/components/templates/icons.js

@@ -235,5 +235,12 @@ export default () => html`
     <symbol id="icon-quote-right" viewBox="0 0 512 512">
         <path d="M464 32H336c-26.5 0-48 21.5-48 48v128c0 26.5 21.5 48 48 48h80v64c0 35.3-28.7 64-64 64h-8c-13.3 0-24 10.7-24 24v48c0 13.3 10.7 24 24 24h8c88.4 0 160-71.6 160-160V80c0-26.5-21.5-48-48-48zm-288 0H48C21.5 32 0 53.5 0 80v128c0 26.5 21.5 48 48 48h80v64c0 35.3-28.7 64-64 64h-8c-13.3 0-24 10.7-24 24v48c0 13.3 10.7 24 24 24h8c88.4 0 160-71.6 160-160V80c0-26.5-21.5-48-48-48z"></path>
     </symbol>
+    <symbol id="icon-bell" viewBox="0 0 512 512">
+        <path d="M224 0c-17.7 0-32 14.3-32 32l0 19.2C119 66 64 130.6 64 208l0 18.8c0 47-17.3 92.4-48.5 127.6l-7.4 8.3c-8.4 9.4-10.4 22.9-5.3 34.4S19.4 416 32 416l384 0c12.6 0 24-7.4 29.2-18.9s3.1-25-5.3-34.4l-7.4-8.3C401.3 319.2 384 273.9 384 226.8l0-18.8c0-77.4-55-142-128-156.8L256 32c0-17.7-14.3-32-32-32zm45.3 493.3c12-12 18.7-28.3 18.7-45.3l-64 0-64 0c0 17 6.7 33.3 18.7 45.3s28.3 18.7 45.3 18.7s33.3-6.7 45.3-18.7z"></path>
+    </symbol>
+    <symbol id="icon-bell-alt" viewBox="0 0 512 512">
+        <path d="M224 0c-17.7 0-32 14.3-32 32l0 19.2C119 66 64 130.6 64 208l0 25.4c0 45.4-15.5 89.5-43.8 124.9L5.3 377c-5.8 7.2-6.9 17.1-2.9 25.4S14.8 416 24 416l400 0c9.2 0 17.6-5.3 21.6-13.6s2.9-18.2-2.9-25.4l-14.9-18.6C399.5 322.9 384 278.8 384 233.4l0-25.4c0-77.4-55-142-128-156.8L256 32c0-17.7-14.3-32-32-32zm0 96c61.9 0 112 50.1 112 112l0 25.4c0 47.9 13.9 94.6 39.7 134.6L72.3 368C98.1 328 112 281.3 112 233.4l0-25.4c0-61.9 50.1-112 112-112zm64 352l-64 0-64 0c0 17 6.7 33.3 18.7 45.3s28.3 18.7 45.3 18.7s33.3-6.7 45.3-18.7s18.7-28.3 18.7-45.3z"></path>
+    </symbol>
+
     </svg>
 `;