Fix the MUC occupant modal and add more info

Fixes #1419
This commit is contained in:
JC Brand 2021-11-19 10:49:22 +01:00
parent a5b73f0309
commit f36c3fefdd
7 changed files with 74 additions and 33 deletions

View File

@ -7,6 +7,7 @@
- Fix trimming of chats in overlayed view mode - Fix trimming of chats in overlayed view mode
- OMEMO bugfix: Always create device session based on real JID. - OMEMO bugfix: Always create device session based on real JID.
- If `auto_register_muc_nickname` is set, make sure to register when the user changes current nick. - If `auto_register_muc_nickname` is set, make sure to register when the user changes current nick.
- #1419: Clicking on avatar should show bigger version
- #2647: Singleton mode doesn't work - #2647: Singleton mode doesn't work
- #2704: Send button doesn't work in a multi-user chat - #2704: Send button doesn't work in a multi-user chat

14
src/modals/modals.scss Normal file
View File

@ -0,0 +1,14 @@
.conversejs {
.modal-body {
.row {
margin-left: 0;
margin-right: 0;
}
}
.occupant-details {
li {
margin-bottom: 1em;
}
}
}

View File

@ -2,42 +2,37 @@ import BootstrapModal from "plugins/modal/base.js";
import tpl_occupant_modal from "./templates/occupant.js"; import tpl_occupant_modal from "./templates/occupant.js";
import { _converse, api } from "@converse/headless/core"; import { _converse, api } from "@converse/headless/core";
import './modals.scss';
const OccupantModal = BootstrapModal.extend({ const OccupantModal = BootstrapModal.extend({
id: "muc-occupant",
initialize () { initialize () {
BootstrapModal.prototype.initialize.apply(this, arguments); BootstrapModal.prototype.initialize.apply(this, arguments);
this.listenTo(this.model, 'change', this.render); if (this.model) {
this.listenTo(this.model, 'change', this.render);
}
/** /**
* Triggered once the OccupantModal has been initialized * Triggered once the OccupantModal has been initialized
* @event _converse#userDetailsModalInitialized * @event _converse#occupantModalInitialized
* @type { _converse.ChatBox } * @type { Object }
* @example _converse.api.listen.on('userDetailsModalInitialized', chatbox => { ... }); * @example _converse.api.listen.on('occupantModalInitialized', data);
*/ */
api.trigger('occupantModalInitialized', this.model); api.trigger('occupantModalInitialized', { 'model': this.model, 'message': this.message });
}, },
toHTML () { toHTML () {
return tpl_occupant_modal(Object.assign( const model = this.model ?? this.message;
this.model.toJSON(), const jid = model?.get('jid');
{ const vcard = _converse.vcards.findWhere({ jid });
'avatar_data': this.getAvatarData(), const display_name = model?.getDisplayName();
'display_name': this.model.getDisplayName() const nick = model.get('nick');
} const occupant_id = model.get('occupant_id');
)); const role = this.model?.get('role');
}, const affiliation = this.model?.get('affiliation');
const hats = this.model?.get('hats')?.length ? this.model.get('hats') : null;
getAvatarData () { return tpl_occupant_modal({ jid, vcard, display_name, nick, occupant_id, role, affiliation, hats });
const vcard = _converse.vcards.findWhere({'jid': this.model.get('jid')});
const image_type = vcard?.get('image_type') || _converse.DEFAULT_IMAGE_TYPE;
const image_data = vcard?.get('image') || _converse.DEFAULT_IMAGE;
const image = "data:" + image_type + ";base64," + image_data;
return {
'classes': 'chat-msg__avatar',
'height': 120,
'width': 120,
image,
};
} }
}); });

View File

@ -1,6 +1,7 @@
import 'shared/avatar/avatar.js';
import { __ } from 'i18n';
import { html } from "lit"; import { html } from "lit";
import { modal_close_button, modal_header_close_button } from "plugins/modal/templates/buttons.js" import { modal_close_button, modal_header_close_button } from "plugins/modal/templates/buttons.js"
import { renderAvatar } from 'shared/directives/avatar';
export default (o) => { export default (o) => {
@ -11,8 +12,34 @@ export default (o) => {
<h5 class="modal-title" id="user-details-modal-label">${o.display_name}</h5> <h5 class="modal-title" id="user-details-modal-label">${o.display_name}</h5>
${modal_header_close_button} ${modal_header_close_button}
</div> </div>
<div class="modal-body"> <div class="modal-body" class="d-flex">
${renderAvatar(o.avatar_data)} <div class="row">
<div class="col-auto">
<converse-avatar class="avatar chat-msg__avatar" .model=${o.vcard} height="120" width="120"></converse-avatar>
</div>
<div class="col">
<ul class="occupant-details">
<li>
${ o.nick ? html`<div class="row"><strong>${__('Nickname')}:</strong></div><div class="row">${o.nick}</div>` : '' }
</li>
<li>
${ o.jid ? html`<div class="row"><strong>${__('XMPP Address')}:</strong></div><div class="row">${o.jid}</div>` : '' }
</li>
<li>
${ o.affiliation ? html`<div class="row"><strong>${__('Affiliation')}:</strong></div><div class="row">${o.affiliation}</div>` : '' }
</li>
<li>
${ o.role ? html`<div class="row"><strong>${__('Roles')}:</strong></div><div class="row">${o.role}</div>` : '' }
</li>
<li>
${ o.hats ? html`<div class="row"><strong>${__('Hats')}:</strong></div><div class="row">${o.hats}</div>` : '' }
</li>
<li>
${ o.occupant_id ? html`<div class="row"><strong>${__('Occupant Id')}:</strong></div><div class="row">${o.occupant_id}</div>` : '' }
</li>
</ul>
</div>
</div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
${modal_close_button} ${modal_close_button}

View File

@ -1,6 +1,6 @@
import { CustomElement } from 'shared/components/element.js'; import { CustomElement } from 'shared/components/element.js';
import tpl_avatar from './templates/avatar.js'; import tpl_avatar from './templates/avatar.js';
import { api } from '@converse/headless/core'; import { _converse, api } from '@converse/headless/core';
export default class Avatar extends CustomElement { export default class Avatar extends CustomElement {
@ -20,12 +20,15 @@ export default class Avatar extends CustomElement {
} }
render () { 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;
return tpl_avatar({ return tpl_avatar({
'classes': this.getAttribute('class'), 'classes': this.getAttribute('class'),
'width': this.width,
'height': this.height, 'height': this.height,
'image_type': this.model?.get('image_type'), 'width': this.width,
'image': this.model?.get('image') image,
image_type,
}); });
} }
} }

View File

@ -229,7 +229,7 @@ export default class Message extends CustomElement {
api.modal.show(_converse.ProfileModal, {model: this.model}, ev); api.modal.show(_converse.ProfileModal, {model: this.model}, ev);
} else if (this.model.get('type') === 'groupchat') { } else if (this.model.get('type') === 'groupchat') {
ev.preventDefault(); ev.preventDefault();
api.modal.show(OccupantModal, { 'model': this.model.occupant }, ev); api.modal.show(OccupantModal, { 'model': this.model.occupant, 'message': this.model }, ev);
} else { } else {
ev.preventDefault(); ev.preventDefault();
const chatbox = this.model.collection.chatbox; const chatbox = this.model.collection.chatbox;

View File

@ -1,3 +1,4 @@
import 'shared/avatar/avatar.js';
import 'shared/chat/unfurl.js'; import 'shared/chat/unfurl.js';
import { __ } from 'i18n'; import { __ } from 'i18n';
import { html } from "lit"; import { html } from "lit";