UNPKG

@jsxc/jsxc

Version:

Real-time XMPP chat application with video calls, file transfer and encrypted communication

219 lines (163 loc) 6.46 kB
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'); } }