浏览代码

Use SVG icons and tweak message padding

JC Brand 3 年之前
父节点
当前提交
bef2cbb462

+ 1 - 9
src/modals/muc-details.js

@@ -1,6 +1,5 @@
 import BootstrapModal from "plugins/modal/base.js";
 import tpl_muc_details from "./templates/muc-details.js";
-import { __ } from 'i18n';
 
 
 export default BootstrapModal.extend({
@@ -15,13 +14,6 @@ export default BootstrapModal.extend({
     },
 
     toHTML () {
-        return tpl_muc_details(Object.assign(
-            this.model.toJSON(), {
-                'config': this.model.config.toJSON(),
-                'display_name': __('Groupchat info for %1$s', this.model.getDisplayName()),
-                'features': this.model.features.toJSON(),
-                'num_occupants': this.model.occupants.length,
-            })
-        );
+        return tpl_muc_details(this.model);
     }
 });

+ 23 - 17
src/modals/templates/muc-details.js

@@ -13,7 +13,13 @@ const subject = (o) => {
 }
 
 
-export default (o) => {
+export default (model) => {
+    const o = model.toJSON();
+    const config = model.config.toJSON();
+    const display_name = __('Groupchat info for %1$s', model.getDisplayName());
+    const features = model.features.toJSON();
+    const num_occupants = model.occupants.filter(o => o.get('show') !== 'offline').length;
+
     const i18n_address =  __('Groupchat XMPP address');
     const i18n_archiving = __('Message archiving');
     const i18n_archiving_help = __('Messages are archived on the server');
@@ -48,7 +54,7 @@ export default (o) => {
         <div class="modal-dialog" role="document">
             <div class="modal-content">
                 <div class="modal-header">
-                    <h5 class="modal-title" id="muc-details-modal-label">${o.display_name}</h5>
+                    <h5 class="modal-title" id="muc-details-modal-label">${display_name}</h5>
                     ${modal_header_close_button}
                 </div>
                 <div class="modal-body">
@@ -56,25 +62,25 @@ export default (o) => {
                     <div class="room-info">
                         <p class="room-info"><strong>${i18n_name}</strong>: ${o.name}</p>
                         <p class="room-info"><strong>${i18n_address}</strong>: ${o.jid}</p>
-                        <p class="room-info"><strong>${i18n_desc}</strong>: ${o.config.description}</p>
+                        <p class="room-info"><strong>${i18n_desc}</strong>: ${config.description}</p>
                         ${ (o.subject) ? subject(o) : '' }
-                        <p class="room-info"><strong>${i18n_online_users}</strong>: ${o.num_occupants}</p>
+                        <p class="room-info"><strong>${i18n_online_users}</strong>: ${num_occupants}</p>
                         <p class="room-info"><strong>${i18n_features}</strong>:
                             <div class="chatroom-features">
                             <ul class="features-list">
-                                ${ o.features.passwordprotected ? html`<li class="feature" ><span class="fa fa-lock"></span>${i18n_password_protected} - <em>${i18n_password_help}</em></li>` : '' }
-                                ${ o.features.unsecured ? html`<li class="feature" ><span class="fa fa-unlock"></span>${i18n_no_password_required} - <em>${i18n_no_pass_help}</em></li>` : '' }
-                                ${ o.features.hidden ? html`<li class="feature" ><span class="fa fa-eye-slash"></span>${i18n_hidden} - <em>${i18n_hidden_help}</em></li>` : '' }
-                                ${ o.features.public_room ? html`<li class="feature" ><span class="fa fa-eye"></span>${i18n_public} - <em>${o.__('This groupchat is publicly searchable') }</em></li>` : '' }
-                                ${ o.features.membersonly ? html`<li class="feature" ><span class="fa fa-address-book"></span>${i18n_members_only} - <em>${i18n_members_help}</em></li>` : '' }
-                                ${ o.features.open ? html`<li class="feature" ><span class="fa fa-globe"></span>${i18n_open} - <em>${i18n_open_help}</em></li>` : '' }
-                                ${ o.features.persistent ? html`<li class="feature" ><span class="fa fa-save"></span>${i18n_persistent} - <em>${i18n_persistent_help}</em></li>` : '' }
-                                ${ o.features.temporary ? html`<li class="feature" ><span class="fa fa-snowflake-o"></span>${i18n_temporary} - <em>${i18n_temporary_help}</em></li>` : '' }
-                                ${ o.features.nonanonymous ? html`<li class="feature" ><span class="fa fa-id-card"></span>${i18n_not_anonymous} - <em>${i18n_not_anonymous_help}</em></li>` : '' }
-                                ${ o.features.semianonymous ? html`<li class="feature" ><span class="fa fa-user-secret"></span>${i18n_semi_anon} - <em>${i18n_semi_anon_help}</em></li>` : '' }
-                                ${ o.features.moderated ? html`<li class="feature" ><span class="fa fa-gavel"></span>${i18n_moderated} - <em>${i18n_moderated_help}</em></li>` : '' }
-                                ${ o.features.unmoderated ? html`<li class="feature" ><span class="fa fa-info-circle"></span>${i18n_not_moderated} - <em>${i18n_not_moderated_help}</em></li>` : '' }
-                                ${ o.features.mam_enabled ? html`<li class="feature" ><span class="fa fa-database"></span>${i18n_archiving} - <em>${i18n_archiving_help}</em></li>` : '' }
+                                ${ features.passwordprotected ? html`<li class="feature" ><converse-icon size="1em" class="fa fa-lock"></converse-icon size="1em">${i18n_password_protected} - <em>${i18n_password_help}</em></li>` : '' }
+                                ${ features.unsecured ? html`<li class="feature" ><converse-icon size="1em" class="fa fa-unlock"></converse-icon size="1em">${i18n_no_password_required} - <em>${i18n_no_pass_help}</em></li>` : '' }
+                                ${ features.hidden ? html`<li class="feature" ><converse-icon size="1em" class="fa fa-eye-slash"></converse-icon size="1em">${i18n_hidden} - <em>${i18n_hidden_help}</em></li>` : '' }
+                                ${ features.public_room ? html`<li class="feature" ><converse-icon size="1em" class="fa fa-eye"></converse-icon size="1em">${i18n_public} - <em>${o.__('This groupchat is publicly searchable') }</em></li>` : '' }
+                                ${ features.membersonly ? html`<li class="feature" ><converse-icon size="1em" class="fa fa-address-book"></converse-icon size="1em">${i18n_members_only} - <em>${i18n_members_help}</em></li>` : '' }
+                                ${ features.open ? html`<li class="feature" ><converse-icon size="1em" class="fa fa-globe"></converse-icon size="1em">${i18n_open} - <em>${i18n_open_help}</em></li>` : '' }
+                                ${ features.persistent ? html`<li class="feature" ><converse-icon size="1em" class="fa fa-save"></converse-icon size="1em">${i18n_persistent} - <em>${i18n_persistent_help}</em></li>` : '' }
+                                ${ features.temporary ? html`<li class="feature" ><converse-icon size="1em" class="fa fa-snowflake-o"></converse-icon size="1em">${i18n_temporary} - <em>${i18n_temporary_help}</em></li>` : '' }
+                                ${ features.nonanonymous ? html`<li class="feature" ><converse-icon size="1em" class="fa fa-id-card"></converse-icon size="1em">${i18n_not_anonymous} - <em>${i18n_not_anonymous_help}</em></li>` : '' }
+                                ${ features.semianonymous ? html`<li class="feature" ><converse-icon size="1em" class="fa fa-user-secret"></converse-icon size="1em">${i18n_semi_anon} - <em>${i18n_semi_anon_help}</em></li>` : '' }
+                                ${ features.moderated ? html`<li class="feature" ><converse-icon size="1em" class="fa fa-gavel"></converse-icon size="1em">${i18n_moderated} - <em>${i18n_moderated_help}</em></li>` : '' }
+                                ${ features.unmoderated ? html`<li class="feature" ><converse-icon size="1em" class="fa fa-info-circle"></converse-icon size="1em">${i18n_not_moderated} - <em>${i18n_not_moderated_help}</em></li>` : '' }
+                                ${ features.mam_enabled ? html`<li class="feature" ><converse-icon size="1em" class="fa fa-database"></converse-icon size="1em">${i18n_archiving} - <em>${i18n_archiving_help}</em></li>` : '' }
                             </ul>
                             </div>
                         </p>

+ 6 - 1
src/modals/templates/user-details.js

@@ -8,7 +8,12 @@ const remove_button = (o) => {
     const i18n_remove_contact = __('Remove as contact');
     return html`
         <button type="button" @click="${o.removeContact}" class="btn btn-danger remove-contact">
-            <i class="far fa-trash-alt"></i>${i18n_remove_contact}
+            <converse-icon
+                class="fas fa-trash-alt"
+                color="var(--text-color-lighten-15-percent)"
+                size="1em"
+            ></converse-icon>
+            ${i18n_remove_contact}
         </button>
     `;
 }

+ 2 - 2
src/plugins/muc-views/modals/muc-list.js

@@ -1,7 +1,7 @@
 import BootstrapModal from "plugins/modal/base.js";
 import head from "lodash-es/head";
 import log from "@converse/headless/log";
-import tpl_list_chatrooms_modal from "../templates/muc-list.js";
+import tpl_muc_list from "../templates/muc-list.js";
 import tpl_muc_description from "../templates/muc-description.js";
 import tpl_spinner from "templates/spinner.js";
 import { __ } from 'i18n';
@@ -87,7 +87,7 @@ export default BootstrapModal.extend({
 
     toHTML () {
         const muc_domain = this.model.get('muc_domain') || api.settings.get('muc_domain');
-        return tpl_list_chatrooms_modal(
+        return tpl_muc_list(
             Object.assign(this.model.toJSON(), {
                 'show_form': !api.settings.get('locked_muc_domain'),
                 'server_placeholder': muc_domain ? muc_domain : __('conference.example.org'),

+ 5 - 5
src/plugins/profile/templates/chat-status-modal.js

@@ -17,32 +17,32 @@ export default (o) => html`
                             <input ?checked=${o.status === 'online'}
                                 type="radio" id="radio-online" value="online" name="chat_status" class="custom-control-input"/>
                             <label class="custom-control-label" for="radio-online">
-                                <span class="fa fa-circle chat-status chat-status--online"></span>${o.label_online}</label>
+                                <converse-icon size="1em" class="fa fa-circle chat-status chat-status--online"></converse-icon>${o.label_online}</label>
                         </div>
                         <div class="custom-control custom-radio">
                             <input ?checked=${o.status === 'busy'}
                                 type="radio" id="radio-busy" value="dnd" name="chat_status" class="custom-control-input"/>
                             <label class="custom-control-label" for="radio-busy">
-                                <span class="fa fa-minus-circle  chat-status chat-status--busy"></span>${o.label_busy}</label>
+                                <converse-icon size="1em" class="fa fa-minus-circle  chat-status chat-status--busy"></converse-icon>${o.label_busy}</label>
                         </div>
                         <div class="custom-control custom-radio">
                             <input ?checked=${o.status === 'away'}
                                 type="radio" id="radio-away" value="away" name="chat_status" class="custom-control-input"/>
                             <label class="custom-control-label" for="radio-away">
-                                <span class="fa fa-circle chat-status chat-status--away"></span>${o.label_away}</label>
+                                <converse-icon size="1em" class="fa fa-circle chat-status chat-status--away"></converse-icon>${o.label_away}</label>
                         </div>
                         <div class="custom-control custom-radio">
                             <input ?checked=${o.status === 'xa'}
                                 type="radio" id="radio-xa" value="xa" name="chat_status" class="custom-control-input"/>
                             <label class="custom-control-label" for="radio-xa">
-                                <span class="far fa-circle chat-status chat-status--xa"></span>${o.label_xa}</label>
+                                <converse-icon size="1em" class="far fa-circle chat-status chat-status--xa"></converse-icon>${o.label_xa}</label>
                         </div>
                     </div>
                     <div class="form-group">
                         <div class="btn-group w-100">
                             <input name="status_message" type="text" class="form-control"
                                 value="${o.status_message || ''}" placeholder="${o.placeholder_status_message}"/>
-                            <span class="clear-input fa fa-times ${o.status_message ? '' : 'hidden'}"></span>
+                            <converse-icon size="1em" class="fa fa-times clear-input ${o.status_message ? '' : 'hidden'}"></converse-icon>
                         </div>
                     </div>
                     <button type="submit" class="btn btn-primary">${o.label_save}</button>

+ 2 - 1
src/plugins/rosterview/filterview.js

@@ -3,6 +3,7 @@ import tpl_roster_filter from "./templates/roster_filter.js";
 import { CustomElement } from 'shared/components/element.js';
 import { Model } from '@converse/skeletor/src/model.js';
 import { _converse, api } from "@converse/headless/core";
+import { ancestor } from 'utils/html.js';
 import { initStorage } from '@converse/headless/utils/storage.js';
 
 export const RosterFilter = Model.extend({
@@ -62,7 +63,7 @@ export class RosterFilterView extends CustomElement {
 
     changeTypeFilter (ev) {
         ev && ev.preventDefault();
-        const type = ev.target.dataset.type;
+        const type = ancestor(ev.target, 'converse-icon')?.dataset.type || 'contacts';
         if (type === 'state') {
             this.model.save({
                 'filter_type': type,

+ 22 - 4
src/plugins/rosterview/styles/roster.scss

@@ -30,10 +30,8 @@
             padding: 0.2em;
         }
 
-        span {
-            padding: 0.3em;
-            min-width: 25px;
-            text-align: center;
+        converse-icon {
+            padding: 0.25em;
         }
 
         .roster-filter {
@@ -56,6 +54,16 @@
         overflow-y: auto;
         color: var(--text-color);
 
+        .roster-group-contacts {
+            .list-item {
+                &:hover {
+                    .list-item-action {
+                        opacity: 1;
+                    }
+                }
+            }
+        }
+
         converse-roster-contact {
             width: 100%;
             overflow: hidden;
@@ -63,6 +71,16 @@
             text-overflow: ellipsis;
             display: flex;
             justify-content: space-between;
+
+            .list-item-action {
+                line-height: 2em;
+            }
+
+            &:hover {
+                .list-item-action {
+                    opacity: 1;
+                }
+            }
         }
 
         .group-toggle {

+ 5 - 5
src/plugins/rosterview/templates/roster_filter.js

@@ -21,18 +21,18 @@ export default (o) => {
             @submit=${o.submitFilter}>
             <div class="form-inline flex-nowrap">
                 <div class="filter-by d-flex flex-nowrap">
-                    <span @click=${o.changeTypeFilter} class="clickable fa fa-user ${ (o.filter_type === 'contacts') ? 'selected' : '' }" data-type="contacts" title="${title_contact_filter}"></span>
-                    <span @click=${o.changeTypeFilter} class="clickable fa fa-users ${ (o.filter_type === 'groups') ? 'selected' : '' }" data-type="groups" title="${title_group_filter}"></span>
-                    <span @click=${o.changeTypeFilter} class="clickable fa fa-circle ${ (o.filter_type === 'state') ? 'selected' : '' }" data-type="state" title="${title_status_filter}"></span>
+                    <converse-icon size="1em" @click=${o.changeTypeFilter} class="fa fa-user clickable ${ (o.filter_type === 'contacts') ? 'selected' : '' }" data-type="contacts" title="${title_contact_filter}"></converse-icon>
+                    <converse-icon size="1em" @click=${o.changeTypeFilter} class="fa fa-users clickable ${ (o.filter_type === 'groups') ? 'selected' : '' }" data-type="groups" title="${title_group_filter}"></converse-icon>
+                    <converse-icon size="1em" @click=${o.changeTypeFilter} class="fa fa-circle clickable ${ (o.filter_type === 'state') ? 'selected' : '' }" data-type="state" title="${title_status_filter}"></converse-icon>
                 </div>
                 <div class="btn-group">
                     <input .value="${o.filter_text || ''}"
                         @keydown=${o.liveFilter}
                         class="roster-filter form-control ${ (o.filter_type === 'state') ? 'hidden' : '' }"
                         placeholder="${i18n_placeholder}"/>
-                    <span class="clear-input fa fa-times ${ (!o.filter_text || o.filter_type === 'state') ? 'hidden' : '' }"
+                    <converse-icon size="1em" class="fa fa-times clear-input ${ (!o.filter_text || o.filter_type === 'state') ? 'hidden' : '' }"
                         @click=${o.clearFilter}>
-                    </span>
+                    </converse-icon>
                 </div>
                 <select class="form-control state-type ${ (o.filter_type !== 'state') ? 'hidden' : '' }"
                         @change=${o.changeChatStateFilter}>

+ 12 - 4
src/plugins/rosterview/templates/roster_item.js

@@ -1,8 +1,17 @@
 import { __ } from 'i18n';
-import { api } from "@converse/headless/core";
+import { api } from "@converse/headless/core.js";
 import { html } from "lit";
 import { STATUSES } from '../constants.js';
 
+const tpl_remove_link = (el, item) => {
+   const display_name = item.getDisplayName();
+   const i18n_remove = __('Click to remove %1$s as a contact', display_name);
+   return html`
+      <a class="list-item-action remove-xmpp-contact" @click=${el.removeContact} title="${i18n_remove}" href="#">
+         <converse-icon class="fa fa-trash-alt" size="1.5em"></converse-icon>
+      </a>
+   `;
+}
 
 export default  (el, item) => {
    const show = item.presence.get('show') || 'offline';
@@ -16,11 +25,10 @@ export default  (el, item) => {
     } else {
         [classes, color] = ['fa fa-circle', 'subdued-color'];
     }
-   const display_name = item.getDisplayName();
    const desc_status = STATUSES[show];
    const num_unread = item.get('num_unread') || 0;
+   const display_name = item.getDisplayName();
    const i18n_chat = __('Click to chat with %1$s (XMPP address: %2$s)', display_name, el.model.get('jid'));
-   const i18n_remove = __('Click to remove %1$s as a contact', display_name);
    return html`
    <a class="list-item-link cbox-list-item open-chat ${ num_unread ? 'unread-msgs' : '' }" title="${i18n_chat}" href="#" @click=${el.openChat}>
       <span>
@@ -38,5 +46,5 @@ export default  (el, item) => {
       ${ num_unread ? html`<span class="msgs-indicator">${ num_unread }</span>` : '' }
       <span class="contact-name contact-name--${el.show} ${ num_unread ? 'unread-msgs' : ''}">${display_name}</span>
    </a>
-   ${ api.settings.get('allow_contact_removal') ? html`<a class="list-item-action remove-xmpp-contact far fa-trash-alt" @click=${el.removeContact} title="${i18n_remove}" href="#"></a>` : '' }`;
+   ${ api.settings.get('allow_contact_removal') ? tpl_remove_link(el, item) : '' }`;
 }

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

@@ -1,4 +1,5 @@
 import './message-history';
+import tpl_spinner from "templates/spinner.js";
 import { CustomElement } from 'shared/components/element.js';
 import { api } from '@converse/headless/core';
 import { html } from 'lit';
@@ -56,7 +57,7 @@ export default class ChatContent extends CustomElement {
                 .model=${this.model}
                 .messages=${[...this.model.messages.models]}>
             </converse-message-history>
-            ${ this.model.ui?.get('chat-content-spinner-top') ? html`<span class="spinner fa fa-spinner centered"></span>` : '' }
+            ${ this.model.ui?.get('chat-content-spinner-top') ? tpl_spinner() : '' }
         `;
     }
 

+ 0 - 1
src/shared/chat/message-actions.js

@@ -57,7 +57,6 @@ class MessageActions extends CustomElement {
             <button class="chat-msg__action ${o.button_class}" @click=${o.handler}>
                 <converse-icon
                     class="${o.icon_class}"
-                    path-prefix="${api.settings.get('assets_path')}"
                     color="var(--text-color-lighten-15-percent)"
                     size="1em"
                 ></converse-icon>

+ 2 - 4
src/shared/chat/toolbar.js

@@ -60,7 +60,7 @@ export class ChatToolbar extends CustomElement {
             const i18n_start_call = __('Start a call');
             buttons.push(html`
                 <button class="toggle-call" @click=${this.toggleCall} title="${i18n_start_call}">
-                    <converse-icon color="var(${color})" class="fa fa-phone" path-prefix="/dist" size="1em"></converse-icon>
+                    <converse-icon color="var(${color})" class="fa fa-phone" size="1em"></converse-icon>
                 </button>`
             );
         }
@@ -90,7 +90,7 @@ export class ChatToolbar extends CustomElement {
                     <converse-icon
                         color="var(--muc-toolbar-btn-color)"
                         class="fa ${this.hidden_occupants ? `fa-angle-double-left` : `fa-angle-double-right`}"
-                        path-prefix="${api.settings.get('assets_path')}" size="1em"></converse-icon>
+                        size="1em"></converse-icon>
                 </button>`
             );
         }
@@ -118,7 +118,6 @@ export class ChatToolbar extends CustomElement {
                     <converse-icon
                         color="var(${color})"
                         class="fa fa-paperclip"
-                        path-prefix="${api.settings.get('assets_path')}"
                         size="1em"></converse-icon>
                 </button>
                 <input type="file" @change=${this.onFileSelection} class="fileupload" multiple="" style="display:none"/>`;
@@ -147,7 +146,6 @@ export class ChatToolbar extends CustomElement {
                 <converse-icon
                     color="var(${color})"
                     class="fa ${this.composing_spoiler ? 'fa-eye-slash' : 'fa-eye'}"
-                    path-prefix="${api.settings.get('assets_path')}"
                     size="1em"></converse-icon>
             </button>`;
 

+ 9 - 2
src/shared/components/styles/icon.scss

@@ -5,12 +5,19 @@ converse-icon {
     svg {
 	fill: var(--subdued-color);
     }
+    &.clickable {
+	&:hover {
+	    svg {
+		fill: var(--icon-hover-color);
+	    }
+	}
+    }
 }
 
 a, .clickable {
     converse-icon {
-	svg {
-	    &:hover {
+	&:hover {
+	    svg {
 		fill: var(--icon-hover-color);
 	    }
 	}

+ 0 - 2
src/shared/directives/retraction.js

@@ -1,5 +1,4 @@
 import { __ } from '../i18n';
-import { api } from "@converse/headless/core";
 import { directive, html } from "lit";
 
 
@@ -8,7 +7,6 @@ const tpl_retract = (o) => html`
     <button class="chat-msg__action chat-msg__action-retract" title="${i18n_retract_message}" @click=${o.onMessageRetractButtonClicked}>
         <converse-icon
             class="fas fa-trash-alt"
-            path-prefix="${api.settings.get("assets_path")}"
             color="var(--text-color-lighten-15-percent)"
             size="1em"
         ></converse-icon>

+ 3 - 11
src/shared/styles/_core.scss

@@ -264,6 +264,9 @@
 
     .selected {
         color: var(--link-color) !important;
+        svg {
+            fill: var(--link-color);
+        }
     }
 
     .circle {
@@ -365,17 +368,6 @@
         }
     }
 
-    .spinner__container {
-      width: 100%;
-    }
-    .spinner {
-        animation: spin 2s infinite, linear;
-        width: 1em;
-        display: block;
-        text-align: center;
-        padding: 0.5em 0;
-        font-size: 24px;
-    }
     .left {
         float: left;
     }

+ 1 - 0
src/shared/styles/index.scss

@@ -32,6 +32,7 @@
 @import "themes/dracula";
 
 @import "core";
+@import "spinner";
 @import "buttons";
 @import "badges";
 @import "forms";

+ 3 - 7
src/shared/styles/messages.scss

@@ -108,11 +108,7 @@
             display: inline-flex;
             width: 100%;
             flex-direction: row;
-            padding: 0 1rem;
-
-            &.chat-msg--with-avatar {
-                padding-top: 0.25rem;
-            }
+            padding: 0.25em 1rem;
 
             &.onload {
                 animation: colorchange-chatmessage 1s;
@@ -144,7 +140,7 @@
                 }
                 &:before {
                     padding-right: 0.25em;
-                    whitespace: nowrap;
+                    white-space: nowrap;
                 }
             }
 
@@ -170,7 +166,7 @@
             }
 
             .chat-msg__message {
-                line-height: 1.5em;
+                line-height: 1.65em;
                 display: inline-flex;
                 flex-direction: column;
                 width: 100%;

+ 19 - 0
src/shared/styles/spinner.scss

@@ -0,0 +1,19 @@
+.conversejs {
+
+    .spinner__container {
+        width: 100%;
+    }
+
+    .spinner {
+        animation: spin 2s infinite, linear;
+        width: 1em;
+        display: block;
+        text-align: center;
+        padding: 0.5em 0;
+        font-size: 24px;
+
+        svg {
+            fill: var(--primary-color);
+        }
+    }
+}

+ 9 - 4
src/shared/styles/status.scss

@@ -17,18 +17,23 @@
     }
     .chat-status--online {
         color: var(--chat-status-online);
+        svg {
+            fill: var(--chat-status-online);
+        }
     }
     .chat-status--busy {
         color: var(--chat-status-busy);
+        svg {
+            fill: var(--chat-status-busy);
+        }
     }
     .chat-status--away {
         color: var(--chat-status-away);
+        svg {
+            fill: var(--chat-status-away);
+        }
     }
     .chat-status--offline {
         display: none;
     }
-    .far.fa-circle,
-    .fa-times-circle {
-        color: var(--subdued-color);
-    }
 }

+ 2 - 2
src/templates/spinner.js

@@ -2,8 +2,8 @@ import { html } from "lit";
 
 export default (o={}) => {
     if (o.classes?.includes('hor_centered')) {
-        return html`<div class="spinner__container"><span class="spinner fa fa-spinner centered ${o.classes || ''}"/></div>`
+        return html`<div class="spinner__container"><converse-icon size="1em" class="fa fa-spinner spinner centered ${o.classes || ''}"></converse-icon></div>`
     } else {
-        return html`<span class="spinner fa fa-spinner centered ${o.classes || ''}"/>`
+        return html`<converse-icon size="1em" class="fa fa-spinner spinner centered ${o.classes || ''}"></converse-icon>`
     }
 }

+ 3 - 3
src/utils/html.js

@@ -200,13 +200,13 @@ u.hideElement = function (el) {
     return el;
 };
 
-u.ancestor = function (el, selector) {
+export function ancestor (el, selector) {
     let parent = el;
     while (parent !== null && !sizzle.matchesSelector(parent, selector)) {
         parent = parent.parentElement;
     }
     return parent;
-};
+}
 
 /**
  * Return the element's siblings until one matches the selector.
@@ -513,6 +513,6 @@ u.xForm2TemplateResult = function (field, stanza, options) {
     }
 };
 
-Object.assign(u, { getOOBURLMarkup });
+Object.assign(u, { getOOBURLMarkup, ancestor });
 
 export default u;