@jsxc/jsxc
Version:
Real-time XMPP chat application with video calls, file transfer and encrypted communication
219 lines (163 loc) • 6.46 kB
text/typescript
import ChatWindow from './ChatWindow';
import MultiUserContact, { AFFILIATION, ROLE } from '../MultiUserContact';
import Translation from '../util/Translation';
import JID from '../JID';
import AvatarSet from './AvatarSet';
import showRoomConfigurationDialog from './dialogs/multiUserRoomConfiguration';
import showMultiUserInviteDialog from './dialogs/multiUserInvite';
import showMultiUserMemberlistDialog from './dialogs/multiUserMemberlist';
export default class MultiUserChatWindow extends ChatWindow {
private memberlistElement;
protected contact: MultiUserContact;
constructor(contact: MultiUserContact) {
super(contact);
this.disable();
this.element.addClass('jsxc-groupchat');
this.addMucElementsToChatWindow();
this.contact.registerNewMemberHook((value, nickname) => {
this.addMember(nickname);
});
this.contact.registerRemoveMemberHook(nickname => {
this.removeMember(nickname);
});
for (let nickname of this.contact.getMemberIds()) {
this.addMember(nickname);
}
this.contact.registerHook('nickname', (newValue, oldValue) => {
if (oldValue && !newValue) {
this.disable();
} else if (!oldValue && newValue) {
this.enable();
}
});
this.contact.getNickname() ? this.enable() : this.disable();
this.contact.registerHook('subject', newSubject => {
this.setBarText(newSubject);
});
this.setBarText(this.contact.getSubject());
this.contact.registerMemberHook(this.contact.getNickname(), data => {
this.updatePermissionAttributes(data);
});
this.updatePermissionAttributes(this.contact.getMember(this.contact.getNickname()));
}
private updatePermissionAttributes(data: { affiliation?: AFFILIATION; role?: ROLE; jid?: JID } = {}) {
this.getDom().attr('data-role', data.role);
this.getDom().attr('data-affiliation', data.affiliation);
}
public addMember(nickname: string) {
let memberElement = this.getMemberElementByNickname(nickname);
if (memberElement.length > 0) {
return;
}
let { jid, affiliation, role } = this.contact.getMember(nickname);
memberElement = $('<li><div class="jsxc-avatar"></div><div class="jsxc-name"/></li>');
memberElement.attr('data-nickname', nickname);
memberElement.attr('data-affiliation', affiliation);
memberElement.attr('data-role', role);
this.memberlistElement.find('ul').append(memberElement);
let title: string;
let label: string;
let avatarElement = memberElement.find('.jsxc-avatar');
if (jid) {
label = `${nickname} (${jid.bare})`;
title = nickname + '\n' + jid.bare;
let contact = this.getAccount().getContact(jid);
if (contact) {
AvatarSet.get(contact).addElement(avatarElement);
} else {
AvatarSet.setPlaceholder(avatarElement, nickname);
}
} else {
label = title = nickname;
AvatarSet.setPlaceholder(avatarElement, nickname);
}
if (nickname === this.contact.getNickname()) {
label = `${nickname} (${Translation.t('you')})`;
}
memberElement.find('.jsxc-name').text(label);
memberElement.attr('title', title);
this.refreshMemberCount();
}
public removeMember(nickname: string) {
let m = this.memberlistElement.find('li[data-nickname="' + nickname.replace(/"/g, '\\"') + '"]');
if (m.length > 0) {
m.remove();
}
this.refreshMemberCount();
}
public emptyMemberList(room) {
this.memberlistElement.empty();
}
private refreshMemberCount() {
this.element.find('.jsxc-members').attr('data-number-of-members', this.memberlistElement.find('li').length || '');
}
protected initDroppable() {
super.initDroppable();
let windowElement = this.element.find('.jsxc-window');
windowElement.on('drop', ev => {
if ((<any>ev.originalEvent).dataTransfer.files.length) {
return;
}
ev.preventDefault();
let jid = new JID((<any>ev.originalEvent).dataTransfer.getData('text'));
this.contact.invite(jid);
});
}
private addMucElementsToChatWindow() {
this.addMemberList();
this.addActionEntry(
'jsxc-members',
this.toggleMemberList,
$('<i class="jsxc-icon-group jsxc-icon--center"></i>')
);
this.addMenuEntry('jsxc-destroy', Translation.t('Destroy'), () => {
this.contact.destroy();
});
this.addMenuEntry('jsxc-configure', Translation.t('Configure'), () => {
showRoomConfigurationDialog(this.contact);
});
this.addMenuEntry('jsxc-managememberlist', Translation.t('Memberlist'), () => {
showMultiUserMemberlistDialog(this.contact);
});
this.addMenuEntry('jsxc-leave', Translation.t('Leave'), () => {
this.contact.leave();
});
this.addMenuEntry('jsxc-invite', Translation.t('Invite'), () => {
showMultiUserInviteDialog(this.contact);
});
}
private addMemberList() {
this.memberlistElement = $('<div class="jsxc-memberlist"><ul></ul></div>');
this.element.find('.jsxc-window-fade').prepend(this.memberlistElement);
}
private toggleMemberList = ev => {
if (ev) {
ev.preventDefault();
}
let ul = this.memberlistElement.find('ul:first');
this.memberlistElement.toggleClass('jsxc-expand');
if (this.memberlistElement.hasClass('jsxc-expand')) {
$('body').click();
$('body').one('click', this.toggleMemberList);
ul.mouseleave(() => {
ul.data('timer', window.setTimeout(this.toggleMemberList, 2000));
}).mouseenter(() => {
window.clearTimeout(ul.data('timer'));
});
} else {
window.clearTimeout(ul.data('timer'));
$('body').off('click', null, this.toggleMemberList);
ul.off('mouseleave mouseenter');
}
return false;
};
private getMemberElementByNickname(nickname: string) {
return this.memberlistElement.find('.li[data-nickname="' + nickname.replace(/"/g, '\\"') + '"]');
}
private enable() {
this.element.removeClass('jsxc-disabled');
}
private disable() {
this.element.addClass('jsxc-disabled');
}
}