Bläddra i källkod

Create the `converse-avatar` custom element

JC Brand 3 år sedan
förälder
incheckning
a5b73f0309

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

@@ -1,4 +1,4 @@
-import avatar from 'shared/templates/avatar.js';
+import avatar from 'shared/avatar/templates/avatar.js';
 import { __ } from 'i18n';
 import { html } from 'lit';
 import { modal_close_button, modal_header_close_button } from 'plugins/modal/templates/buttons.js'

+ 0 - 2
src/plugins/chatboxviews/index.js

@@ -6,7 +6,6 @@
 import './view.js';
 import '@converse/headless/plugins/chatboxes/index.js';
 import ChatBoxViews from './container.js';
-import { ViewWithAvatar } from 'shared/avatar.js';
 import { _converse, api, converse } from '@converse/headless/core';
 import { calculateViewportHeightUnit } from './utils.js';
 
@@ -28,7 +27,6 @@ converse.plugins.add('converse-chatboxviews', {
             'theme': 'default'
         });
 
-        _converse.ViewWithAvatar = ViewWithAvatar;
         _converse.chatboxviews = new ChatBoxViews();
 
         /************************ BEGIN Event Handlers ************************/

+ 6 - 39
src/plugins/profile/statusview.js

@@ -1,54 +1,21 @@
 import UserSettingsModal from 'modals/user-settings';
 import tpl_profile from './templates/profile.js';
-import { ElementViewWithAvatar } from 'shared/avatar.js';
+import { CustomElement } from 'shared/components/element.js';
 import { __ } from 'i18n';
 import { _converse, api } from '@converse/headless/core';
-import { render } from 'lit';
 
-
-function getPrettyStatus (stat) {
-    if (stat === 'chat') {
-        return __('online');
-    } else if (stat === 'dnd') {
-        return __('busy');
-    } else if (stat === 'xa') {
-        return __('away for long');
-    } else if (stat === 'away') {
-        return __('away');
-    } else if (stat === 'offline') {
-        return __('offline');
-    } else {
-        return __(stat) || __('online');
-    }
-}
-
-
-class ProfileView extends ElementViewWithAvatar {
+class ProfileView extends CustomElement {
 
     async initialize () {
         this.model = _converse.xmppstatus;
-        this.listenTo(this.model, "change", this.render);
+        this.listenTo(this.model, "change", this.requestUpdate);
         await api.waitUntil('VCardsInitialized');
-        this.listenTo(this.model.vcard, "change", this.render);
-        this.render();
+        this.listenTo(this.model.vcard, "change", this.requestUpdate);
+        this.requestUpdate();
     }
 
     render () {
-        const chat_status = this.model.get('status') || 'offline';
-        render(tpl_profile(Object.assign(
-            this.model.toJSON(),
-            this.model.vcard.toJSON(), {
-            chat_status,
-            'fullname': this.model.vcard.get('fullname') || _converse.bare_jid,
-            "showUserSettingsModal": ev => this.showUserSettingsModal(ev),
-            'status_message': this.model.get('status_message') ||
-                                __("I am %1$s", getPrettyStatus(chat_status)),
-            'logout': this.logout,
-            'showStatusChangeModal': () => this.showStatusChangeModal(),
-            'showProfileModal': () => this.showProfileModal()
-        })), this);
-
-        this.renderAvatar();
+        return tpl_profile(this);
     }
 
     showProfileModal (ev) {

+ 18 - 13
src/plugins/profile/templates/profile.js

@@ -1,5 +1,7 @@
+import 'shared/avatar/avatar.js';
 import { __ } from 'i18n';
-import { api } from "@converse/headless/core";
+import { _converse, api } from "@converse/headless/core";
+import { getPrettyStatus } from '../utils.js';
 import { html } from "lit";
 
 
@@ -17,15 +19,18 @@ function tpl_user_settings_button (o) {
     </a>`;
 }
 
-export default (o) => {
+export default (el) => {
+    const chat_status = el.model.get('status') || 'offline';
+    const fullname = el.model.vcard?.get('fullname') || _converse.bare_jid;
+    const status_message = el.model.get('status_message') || __("I am %1$s", getPrettyStatus(chat_status));
     const i18n_change_status = __('Click to change your chat status');
     const show_settings_button = api.settings.get('show_client_info') || api.settings.get('allow_adhoc_commands');
     let classes, color;
-    if (o.chat_status === 'online') {
+    if (chat_status === 'online') {
         [classes, color] = ['fa fa-circle chat-status', 'chat-status-online'];
-    } else if (o.chat_status === 'dnd') {
+    } else if (chat_status === 'dnd') {
         [classes, color] =  ['fa fa-minus-circle chat-status', 'chat-status-busy'];
-    } else if (o.chat_status === 'away') {
+    } else if (chat_status === 'away') {
         [classes, color] =  ['fa fa-circle chat-status', 'chat-status-away'];
     } else {
         [classes, color] = ['fa fa-circle chat-status', 'subdued-color'];
@@ -33,17 +38,17 @@ export default (o) => {
     return html`
         <div class="userinfo controlbox-padded">
             <div class="controlbox-section profile d-flex">
-                <a class="show-profile" href="#" @click=${o.showProfileModal}>
-                    <canvas class="avatar align-self-center" height="40" width="40"></canvas>
+                <a class="show-profile" href="#" @click=${el.showProfileModal}>
+                    <converse-avatar class="avatar align-self-center" .model=${el.model.vcard} height="40" width="40"></converse-avatar>
                 </a>
-                <span class="username w-100 align-self-center">${o.fullname}</span>
-                ${show_settings_button  ? tpl_user_settings_button(o) : ''}
-                ${api.settings.get('allow_logout') ? tpl_signout(o) : ''}
+                <span class="username w-100 align-self-center">${fullname}</span>
+                ${show_settings_button  ? tpl_user_settings_button(el) : ''}
+                ${api.settings.get('allow_logout') ? tpl_signout(el) : ''}
             </div>
             <div class="d-flex xmpp-status">
-                <a class="change-status" title="${i18n_change_status}" data-toggle="modal" data-target="#changeStatusModal" @click=${o.showStatusChangeModal}>
-                    <span class="${o.chat_status} w-100 align-self-center" data-value="${o.chat_status}">
-                    <converse-icon color="var(--${color})" size="1em" class="${classes}"></converse-icon> ${o.status_message}</span>
+                <a class="change-status" title="${i18n_change_status}" data-toggle="modal" data-target="#changeStatusModal" @click=${el.showStatusChangeModal}>
+                    <span class="${chat_status} w-100 align-self-center" data-value="${chat_status}">
+                    <converse-icon color="var(--${color})" size="1em" class="${classes}"></converse-icon> ${status_message}</span>
                 </a>
             </div>
         </div>`

+ 17 - 0
src/plugins/profile/utils.js

@@ -0,0 +1,17 @@
+import { __ } from 'i18n';
+
+export function getPrettyStatus (stat) {
+    if (stat === 'chat') {
+        return __('online');
+    } else if (stat === 'dnd') {
+        return __('busy');
+    } else if (stat === 'xa') {
+        return __('away for long');
+    } else if (stat === 'away') {
+        return __('away');
+    } else if (stat === 'offline') {
+        return __('offline');
+    } else {
+        return __(stat) || __('online');
+    }
+}

+ 33 - 0
src/shared/avatar/avatar.js

@@ -0,0 +1,33 @@
+import { CustomElement } from 'shared/components/element.js';
+import tpl_avatar from './templates/avatar.js';
+import { api } from '@converse/headless/core';
+
+
+export default class Avatar extends CustomElement {
+
+    static get properties () {
+        return {
+            model: { type: Object },
+            width: { type: String },
+            height: { type: String },
+        }
+    }
+
+    constructor () {
+        super();
+        this.width = 36;
+        this.height = 36;
+    }
+
+    render  () {
+        return tpl_avatar({
+            'classes': this.getAttribute('class'),
+            'width': this.width,
+            'height': this.height,
+            'image_type': this.model?.get('image_type'),
+            'image': this.model?.get('image')
+        });
+    }
+}
+
+api.elements.define('converse-avatar', Avatar);

+ 0 - 0
src/shared/templates/avatar.js → src/shared/avatar/templates/avatar.js


+ 0 - 0
src/shared/avatar.js → src/shared/avatar/view.js


+ 2 - 14
src/shared/chat/message.js

@@ -2,10 +2,10 @@ import './message-actions.js';
 import './message-body.js';
 import 'shared/components/dropdown.js';
 import 'shared/registry';
+import tpl_file_progress from './templates/file-progress.js';
 import MessageVersionsModal from 'modals/message-versions.js';
 import OccupantModal from 'modals/occupant.js';
 import UserDetailsModal from 'modals/user-details.js';
-import filesize from 'filesize';
 import log from '@converse/headless/log';
 import tpl_info_message from './templates/info-message.js';
 import tpl_mep_message from 'plugins/muc-views/templates/mep-message.js';
@@ -18,8 +18,6 @@ import { __ } from 'i18n';
 import { _converse, api, converse } from  '@converse/headless/core';
 import { getAppSettings } from '@converse/headless/shared/settings/utils.js';
 import { getHats } from './utils.js';
-import { html } from 'lit';
-import { renderAvatar } from 'shared/directives/avatar';
 
 const { Strophe, dayjs } = converse.env;
 
@@ -116,17 +114,7 @@ export default class Message extends CustomElement {
             // Can happen when file upload failed and page was reloaded
             return '';
         }
-        const i18n_uploading = __('Uploading file:');
-        const filename = this.model.file.name;
-        const size = filesize(this.model.file.size);
-        return html`
-            <div class="message chat-msg">
-                ${ renderAvatar(this.getAvatarData()) }
-                <div class="chat-msg__content">
-                    <span class="chat-msg__text">${i18n_uploading} <strong>${filename}</strong>, ${size}</span>
-                    <progress value="${this.model.get('progress')}"/>
-                </div>
-            </div>`;
+        return tpl_file_progress(this);
     }
 
     renderChatMessage () {

+ 24 - 0
src/shared/chat/templates/file-progress.js

@@ -0,0 +1,24 @@
+import 'shared/avatar/avatar.js';
+import filesize from 'filesize';
+import { __ } from 'i18n';
+import { html } from 'lit';
+
+export default (el) => {
+    const i18n_uploading = __('Uploading file:');
+    const filename = el.model.file.name;
+    const size = filesize(el.model.file.size);
+    return html`
+        <div class="message chat-msg">
+            <converse-avatar class="avatar align-self-center" .model=${el.model.vcard} height="40" width="40"></converse-avatar>
+
+            ${ el.shouldShowAvatar() ?
+                html`<a class="show-msg-author-modal" @click=${el.showUserModal}>
+                    <converse-avatar class="avatar align-self-center" .model=${el.model.vcard} height="40" width="40"></converse-avatar>
+                </a>` : '' }
+
+            <div class="chat-msg__content">
+                <span class="chat-msg__text">${i18n_uploading} <strong>${filename}</strong>, ${size}</span>
+                <progress value="${el.model.get('progress')}"/>
+            </div>
+        </div>`;
+}

+ 5 - 2
src/shared/chat/templates/message.js

@@ -1,7 +1,6 @@
 import 'shared/chat/unfurl.js';
 import { __ } from 'i18n';
 import { html } from "lit";
-import { renderAvatar } from 'shared/directives/avatar';
 import { shouldRenderMediaFromURL } from '@converse/headless/utils/url.js';
 
 
@@ -18,7 +17,11 @@ export default (el, o) => {
             <!-- Anchor to allow us to scroll the message into view -->
             <a id="${o.msgid}"></a>
 
-            <a class="show-msg-author-modal" @click=${el.showUserModal}>${ o.should_show_avatar ? renderAvatar(el.getAvatarData()) : '' }</a>
+            ${ o.should_show_avatar ?
+                html`<a class="show-msg-author-modal" @click=${el.showUserModal}>
+                    <converse-avatar class="avatar align-self-center" .model=${el.model.vcard} height="40" width="40"></converse-avatar>
+                </a>` : '' }
+
             <div class="chat-msg__content chat-msg__content--${o.sender} ${o.is_me_message ? 'chat-msg__content--action' : ''}">
 
                 ${ !o.is_me_message ? html`

+ 1 - 1
src/shared/directives/avatar.js

@@ -1,4 +1,4 @@
-import tpl_avatar from 'shared/templates/avatar.js';
+import tpl_avatar from 'shared/avatar/templates/avatar.js';
 import { Directive, directive } from "lit/directive.js";
 
 

+ 0 - 17
src/templates/file_progress.js

@@ -1,17 +0,0 @@
-import { __ } from '../i18n';
-import { html } from "lit";
-import { renderAvatar } from './../templates/directives/avatar';
-
-
-export default (o) => {
-    const i18n_uploading = __('Uploading file:')
-    return html`
-        <div class="message chat-msg" data-isodate="${o.time}" data-msgid="${o.msgid}">
-            ${ renderAvatar(this) }
-            <div class="chat-msg__content">
-                <span class="chat-msg__text">${i18n_uploading} <strong>${o.filename}</strong>, ${o.filesize}</span>
-                <progress value="${o.progress}"/>
-            </div>
-        </div>
-    `;
-}