Use converse-avatar for setting avatar
This commit is contained in:
parent
c62ea03e2e
commit
664f290001
|
@ -209,11 +209,13 @@ converse.plugins.add('converse-vcard', {
|
|||
return;
|
||||
} else {
|
||||
message.vcard = getVCardForChatroomOccupant(message);
|
||||
message.vcard.on('change', () => message.trigger('vcard:change'));
|
||||
message.trigger('vcard:add');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
_converse.initVCardCollection = async function () {
|
||||
async function initVCardCollection () {
|
||||
_converse.vcards = new _converse.VCards();
|
||||
const id = `${_converse.bare_jid}-converse.vcards`;
|
||||
initStorage(_converse.vcards, id);
|
||||
|
@ -226,7 +228,12 @@ converse.plugins.add('converse-vcard', {
|
|||
const vcards = _converse.vcards;
|
||||
if (_converse.session) {
|
||||
const jid = _converse.session.get('bare_jid');
|
||||
_converse.xmppstatus.vcard = vcards.findWhere({'jid': jid}) || vcards.create({'jid': jid});
|
||||
const status = _converse.xmppstatus;
|
||||
status.vcard = vcards.findWhere({'jid': jid}) || vcards.create({'jid': jid});
|
||||
if (status.vcard) {
|
||||
status.vcard.on('change', () => status.trigger('vcard:change'));
|
||||
status.trigger('vcard:add');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Triggered as soon as the `_converse.vcards` collection has been initialized and populated from cache.
|
||||
|
@ -256,7 +263,7 @@ converse.plugins.add('converse-vcard', {
|
|||
api.listen.on('clearSession', () => clearVCardsSession());
|
||||
api.listen.on('messageInitialized', m => setVCardOnModel(m));
|
||||
api.listen.on('rosterContactInitialized', m => setVCardOnModel(m));
|
||||
api.listen.on('statusInitialized', _converse.initVCardCollection);
|
||||
api.listen.on('statusInitialized', initVCardCollection);
|
||||
|
||||
|
||||
/************************ BEGIN API ************************/
|
||||
|
|
|
@ -15,7 +15,11 @@ export default (o) => {
|
|||
<div class="modal-body" class="d-flex">
|
||||
<div class="row">
|
||||
<div class="col-auto">
|
||||
<converse-avatar class="avatar chat-msg__avatar" .model=${o.vcard} height="120" width="120"></converse-avatar>
|
||||
<converse-avatar
|
||||
class="avatar chat-msg__avatar"
|
||||
.data=${o.vcard?.attributes}
|
||||
nonce=${o.vcard?.get('vcard_updated')}
|
||||
height="120" width="120"></converse-avatar>
|
||||
</div>
|
||||
<div class="col">
|
||||
<ul class="occupant-details">
|
||||
|
|
|
@ -19,7 +19,12 @@ async function getDropdownButtons (promise) {
|
|||
|
||||
export default (o) => {
|
||||
const i18n_profile = __("The User's Profile Image");
|
||||
const avatar = html`<span title="${i18n_profile}"><converse-avatar class="avatar chat-msg__avatar" .model=${o.model.vcard} height="40" width="40"></converse-avatar></span>`;
|
||||
const avatar = html`<span title="${i18n_profile}">
|
||||
<converse-avatar
|
||||
class="avatar chat-msg__avatar"
|
||||
.data=${o.model.vcard?.attributes}
|
||||
nonce=${o.model.vcard?.get('vcard_updated')}
|
||||
height="40" width="40"></converse-avatar></span>`;
|
||||
const display_name = o.model.getDisplayName();
|
||||
|
||||
const tpl_dropdown_btns = () => getDropdownButtons(o.heading_buttons_promise)
|
||||
|
|
|
@ -30,22 +30,10 @@ const ProfileModal = BootstrapModal.extend({
|
|||
return tpl_profile_modal(Object.assign(
|
||||
this.model.toJSON(),
|
||||
this.model.vcard.toJSON(),
|
||||
this.getAvatarData(),
|
||||
{ 'view': this }
|
||||
));
|
||||
},
|
||||
|
||||
getAvatarData () {
|
||||
const image_type = this.model.vcard.get('image_type');
|
||||
const image_data = this.model.vcard.get('image');
|
||||
const image = "data:" + image_type + ";base64," + image_data;
|
||||
return {
|
||||
'height': 128,
|
||||
'width': 128,
|
||||
image,
|
||||
};
|
||||
},
|
||||
|
||||
afterRender () {
|
||||
this.tabs = sizzle('.nav-item .nav-link', this.el).map(e => new bootstrap.Tab(e));
|
||||
},
|
||||
|
|
|
@ -6,12 +6,11 @@ import { _converse, api } from '@converse/headless/core';
|
|||
|
||||
class ProfileView extends CustomElement {
|
||||
|
||||
async initialize () {
|
||||
initialize () {
|
||||
this.model = _converse.xmppstatus;
|
||||
this.listenTo(this.model, "vcard:add", this.requestUpdate);
|
||||
this.listenTo(this.model, "change", this.requestUpdate);
|
||||
await api.waitUntil('VCardsInitialized');
|
||||
this.listenTo(this.model.vcard, "change", this.requestUpdate);
|
||||
this.requestUpdate();
|
||||
this.listenTo(this.model, "vcard:change", this.requestUpdate);
|
||||
}
|
||||
|
||||
render () {
|
||||
|
|
|
@ -39,7 +39,10 @@ export default (el) => {
|
|||
<div class="userinfo controlbox-padded">
|
||||
<div class="controlbox-section profile d-flex">
|
||||
<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>
|
||||
<converse-avatar class="avatar align-self-center"
|
||||
.data=${el.model.vcard?.attributes}
|
||||
nonce=${el.model.vcard?.get('vcard_updated')}
|
||||
height="40" width="40"></converse-avatar>
|
||||
</a>
|
||||
<span class="username w-100 align-self-center">${fullname}</span>
|
||||
${show_settings_button ? tpl_user_settings_button(el) : ''}
|
||||
|
|
|
@ -125,7 +125,7 @@ export default (o) => {
|
|||
<form class="converse-form converse-form--modal profile-form" action="#">
|
||||
<div class="row">
|
||||
<div class="col-auto">
|
||||
<converse-image-picker image="${o.image}" width="${o.width}" height="${o.height}"></converse-image-picker>
|
||||
<converse-image-picker .data="${{image: o.image, image_type: o.image_type}}" width="128" height="128"></converse-image-picker>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="form-group">
|
||||
|
|
|
@ -25,7 +25,11 @@ export default (el, item) => {
|
|||
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}>
|
||||
<converse-avatar class="avatar" .model=${el.model.vcard} height="30" width="30"></converse-avatar>
|
||||
<converse-avatar
|
||||
class="avatar"
|
||||
.data=${el.model.vcard?.attributes}
|
||||
nonce=${el.model.vcard?.get('vcard_updated')}
|
||||
height="30" width="30"></converse-avatar>
|
||||
<span class="${status_icon}" title="${desc_status}"></span>
|
||||
${ 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>
|
||||
|
|
|
@ -9,9 +9,10 @@ export default class Avatar extends CustomElement {
|
|||
|
||||
static get properties () {
|
||||
return {
|
||||
model: { type: Object },
|
||||
data: { type: Object },
|
||||
width: { type: String },
|
||||
height: { type: String },
|
||||
nonce: { type: String }, // Used to trigger rerenders
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,9 +23,14 @@ export default class Avatar extends CustomElement {
|
|||
}
|
||||
|
||||
render () {
|
||||
const image_type = this.model?.get('image_type') || _converse.DEFAULT_IMAGE_TYPE;
|
||||
const image_data = this.model?.get('image') || _converse.DEFAULT_IMAGE;
|
||||
const image = "data:" + image_type + ";base64," + image_data;
|
||||
const image_type = this.data?.image_type || _converse.DEFAULT_IMAGE_TYPE;
|
||||
let image;
|
||||
if (this.data?.data_uri) {
|
||||
image = this.data?.data_uri;
|
||||
} else {
|
||||
const image_data = this.data?.image || _converse.DEFAULT_IMAGE;
|
||||
image = "data:" + image_type + ";base64," + image_data;
|
||||
}
|
||||
return tpl_avatar({
|
||||
'classes': this.getAttribute('class'),
|
||||
'height': this.height,
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
import tpl_avatar from 'shared/templates/avatar.js';
|
||||
import { ElementView } from '@converse/skeletor/src/element';
|
||||
import { View } from '@converse/skeletor/src/view';
|
||||
import { converse } from '@converse/headless/core';
|
||||
|
||||
const u = converse.env.utils;
|
||||
|
||||
const AvatarMixin = {
|
||||
|
||||
renderAvatar (el) {
|
||||
el = el || (this?.el ?? this);
|
||||
const avatar_el = el.querySelector('canvas.avatar, svg.avatar');
|
||||
if (avatar_el === null) {
|
||||
return;
|
||||
}
|
||||
if (this.model.vcard) {
|
||||
const data = {
|
||||
'classes': avatar_el.getAttribute('class'),
|
||||
'width': avatar_el.getAttribute('width'),
|
||||
'height': avatar_el.getAttribute('height'),
|
||||
'image_type': this.model.vcard.get('image_type'),
|
||||
'image': this.model.vcard.get('image')
|
||||
};
|
||||
avatar_el.outerHTML = u.getElementFromTemplateResult(tpl_avatar(data)).outerHTML;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export const ViewWithAvatar = View.extend(AvatarMixin);
|
||||
|
||||
|
||||
export class ElementViewWithAvatar extends ElementView {
|
||||
|
||||
renderAvatar (el) {
|
||||
AvatarMixin.renderAvatar.call(this, el);
|
||||
}
|
||||
}
|
|
@ -127,18 +127,6 @@ export default class Message extends CustomElement {
|
|||
['chat', 'groupchat'].includes(this.model.get('type'));
|
||||
}
|
||||
|
||||
getAvatarData () {
|
||||
const image_type = this.model.vcard?.get('image_type') || _converse.DEFAULT_IMAGE_TYPE;
|
||||
const image_data = this.model.vcard?.get('image') || _converse.DEFAULT_IMAGE;
|
||||
const image = "data:" + image_type + ";base64," + image_data;
|
||||
return {
|
||||
'classes': 'chat-msg__avatar',
|
||||
'height': 36,
|
||||
'width': 36,
|
||||
image,
|
||||
};
|
||||
}
|
||||
|
||||
onUnfurlAnimationEnd () {
|
||||
if (this.model.get('url_preview_transition') === 'fade-out') {
|
||||
this.model.save({
|
||||
|
|
|
@ -9,13 +9,13 @@ export default (el) => {
|
|||
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>
|
||||
<converse-avatar class="avatar align-self-center"
|
||||
.data=${el.model.vcard?.attributes}
|
||||
nonce=${el.model.vcard?.get('vcard_updated')}
|
||||
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')}"/>
|
||||
|
|
|
@ -20,7 +20,11 @@ export default (el, o) => {
|
|||
|
||||
${ 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>
|
||||
<converse-avatar
|
||||
class="avatar align-self-center"
|
||||
.data=${el.model.vcard?.attributes}
|
||||
nonce=${el.model.vcard?.get('vcard_updated')}
|
||||
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' : ''}">
|
||||
|
|
|
@ -2,7 +2,6 @@ import { CustomElement } from './element.js';
|
|||
import { __ } from 'i18n';
|
||||
import { api } from "@converse/headless/core";
|
||||
import { html } from 'lit';
|
||||
import { renderAvatar } from "shared/directives/avatar.js";
|
||||
|
||||
const i18n_profile_picture = __('Your profile picture');
|
||||
|
||||
|
@ -12,20 +11,15 @@ export default class ImagePicker extends CustomElement {
|
|||
static get properties () {
|
||||
return {
|
||||
'height': { type: Number },
|
||||
'image': { type: String },
|
||||
'data': { type: Object},
|
||||
'width': { type: Number },
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const avatar_data = {
|
||||
'height': this.height,
|
||||
'image': this.image,
|
||||
'width': this.width,
|
||||
};
|
||||
return html`
|
||||
<a class="change-avatar" @click=${this.openFileSelection} title="${i18n_profile_picture}">
|
||||
${ renderAvatar(avatar_data) }
|
||||
<converse-avatar class="avatar" .data=${this.data} height="${this.height}" width="${this.width}"></converse-avatar>
|
||||
</a>
|
||||
<input @change=${this.updateFilePreview} class="hidden" name="image" type="file"/>
|
||||
`;
|
||||
|
@ -39,7 +33,12 @@ export default class ImagePicker extends CustomElement {
|
|||
updateFilePreview (ev) {
|
||||
const file = ev.target.files[0];
|
||||
const reader = new FileReader();
|
||||
reader.onloadend = () => (this.image = reader.result);
|
||||
reader.onloadend = () => {
|
||||
this.data = {
|
||||
'data_uri': reader.result,
|
||||
'image_type': file.type
|
||||
}
|
||||
}
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
import tpl_avatar from 'shared/avatar/templates/avatar.js';
|
||||
import { Directive, directive } from "lit/directive.js";
|
||||
|
||||
|
||||
class AvatarDirective extends Directive {
|
||||
|
||||
render (o) { // eslint-disable-line class-methods-use-this
|
||||
const data = {
|
||||
'classes': o.classes ? `${o.classes} avatar` : 'avatar',
|
||||
'height': o.width || 36,
|
||||
'image': o.image,
|
||||
'image_type': o.image_type,
|
||||
'width': o.height || 36,
|
||||
}
|
||||
return tpl_avatar(data);
|
||||
}
|
||||
}
|
||||
|
||||
export const renderAvatar = directive(AvatarDirective);
|
Loading…
Reference in New Issue
Block a user