diff --git a/src/modals/templates/user-details.js b/src/modals/templates/user-details.js
index 4c4187862..c16b1c8fe 100644
--- a/src/modals/templates/user-details.js
+++ b/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'
diff --git a/src/plugins/chatboxviews/index.js b/src/plugins/chatboxviews/index.js
index 6cc518940..1fcb9b457 100644
--- a/src/plugins/chatboxviews/index.js
+++ b/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 ************************/
diff --git a/src/plugins/profile/statusview.js b/src/plugins/profile/statusview.js
index 40ee3f4f2..b9c9fb204 100644
--- a/src/plugins/profile/statusview.js
+++ b/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) {
diff --git a/src/plugins/profile/templates/profile.js b/src/plugins/profile/templates/profile.js
index 83eac1978..34506c94b 100644
--- a/src/plugins/profile/templates/profile.js
+++ b/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) {
`;
}
-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`
-
-
+
+
-
${o.fullname}
- ${show_settings_button ? tpl_user_settings_button(o) : ''}
- ${api.settings.get('allow_logout') ? tpl_signout(o) : ''}
+
${fullname}
+ ${show_settings_button ? tpl_user_settings_button(el) : ''}
+ ${api.settings.get('allow_logout') ? tpl_signout(el) : ''}
`
diff --git a/src/plugins/profile/utils.js b/src/plugins/profile/utils.js
new file mode 100644
index 000000000..51f14c207
--- /dev/null
+++ b/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');
+ }
+}
diff --git a/src/shared/avatar/avatar.js b/src/shared/avatar/avatar.js
new file mode 100644
index 000000000..bf00868ab
--- /dev/null
+++ b/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);
diff --git a/src/shared/templates/avatar.js b/src/shared/avatar/templates/avatar.js
similarity index 100%
rename from src/shared/templates/avatar.js
rename to src/shared/avatar/templates/avatar.js
diff --git a/src/shared/avatar.js b/src/shared/avatar/view.js
similarity index 100%
rename from src/shared/avatar.js
rename to src/shared/avatar/view.js
diff --git a/src/shared/chat/message.js b/src/shared/chat/message.js
index 71b24f3af..9b93df4b7 100644
--- a/src/shared/chat/message.js
+++ b/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`
-
- ${ renderAvatar(this.getAvatarData()) }
-
-
${i18n_uploading} ${filename}, ${size}
-
-
-
`;
+ return tpl_file_progress(this);
}
renderChatMessage () {
diff --git a/src/shared/chat/templates/file-progress.js b/src/shared/chat/templates/file-progress.js
new file mode 100644
index 000000000..7daa06e70
--- /dev/null
+++ b/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`
+
+
+
+ ${ el.shouldShowAvatar() ?
+ html`
+
+ ` : '' }
+
+
+
${i18n_uploading} ${filename}, ${size}
+
+
+
`;
+}
diff --git a/src/shared/chat/templates/message.js b/src/shared/chat/templates/message.js
index 940797ee8..fb7e531b3 100644
--- a/src/shared/chat/templates/message.js
+++ b/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) => {
- ${ o.should_show_avatar ? renderAvatar(el.getAvatarData()) : '' }
+ ${ o.should_show_avatar ?
+ html`
+
+ ` : '' }
+
${ !o.is_me_message ? html`
diff --git a/src/shared/directives/avatar.js b/src/shared/directives/avatar.js
index fa4c108ac..b55036aeb 100644
--- a/src/shared/directives/avatar.js
+++ b/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";
diff --git a/src/templates/file_progress.js b/src/templates/file_progress.js
deleted file mode 100644
index dd9e78d6a..000000000
--- a/src/templates/file_progress.js
+++ /dev/null
@@ -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`
-
- ${ renderAvatar(this) }
-
-
${i18n_uploading} ${o.filename}, ${o.filesize}
-
-
-
- `;
-}