@jsxc/jsxc
Version:
Real-time XMPP chat application with video calls, file transfer and encrypted communication
163 lines (126 loc) • 4.65 kB
text/typescript
import ContactProvider from '@src/ContactProvider';
import AbstractService from './services/AbstractService';
import RoomBookmark from './RoomBookmark';
import MultiUserContact, { ROOMCONFIG } from '@src/MultiUserContact';
import { IJID } from '@src/JID.interface';
import { IContact, ContactType } from '@src/Contact.interface';
import ContactManager from '@src/ContactManager';
import RoleAllocator from '@src/RoleAllocator';
export default class BookmarkProvider extends ContactProvider {
private services: { [name: string]: AbstractService } = {};
constructor(
contactManager: ContactManager,
private createMultiUserContact: (jid: IJID, name?: string) => MultiUserContact
) {
super(contactManager);
}
public getUid(): string {
return 'bookmark';
}
public async add(contact: MultiUserContact): Promise<boolean> {
if (contact.getType() !== ContactType.GROUPCHAT) {
return false;
}
let bookmark = this.contactToBookmark(contact);
try {
await this.addToServices(bookmark);
} catch (err) {
return false;
}
contact.setProvider(this);
this.registerContact(contact);
this.contactManager.addToCache(contact);
return true;
}
public addToServices(bookmark: RoomBookmark): Promise<any> {
let results = [];
for (let name in this.services) {
let service = this.services[name];
results.push(service.addRoom(bookmark));
}
return Promise.all(results);
}
private contactToBookmark(contact: MultiUserContact): RoomBookmark {
let id = contact.getJid();
let alias = contact.hasName() ? contact.getName() : undefined;
let nickname = contact.getNickname();
let autoJoin = contact.isAutoJoin();
let password = contact.getPassword();
return new RoomBookmark(id, alias, nickname, autoJoin, password);
}
public createContact(jid: IJID, name?: string): MultiUserContact;
public createContact(id: string): MultiUserContact;
public createContact() {
let contact = this.createMultiUserContact(arguments[0], arguments[1]);
this.registerContact(contact);
return contact;
}
private registerContact(contact: MultiUserContact) {
//@TODO add hooks for more settings
//@TODO delay update to aggregate changes
contact.registerHook('name', () => {
if (RoleAllocator.get().isMaster()) {
this.updateContact(contact);
}
});
}
private updateContact(contact: MultiUserContact): Promise<any> {
let bookmark = this.contactToBookmark(contact);
return this.addToServices(bookmark);
}
public registerService(service: AbstractService) {
this.services[service.getName()] = service;
}
public async deleteContact(jid: IJID): Promise<void> {
let results = [];
for (let name in this.services) {
let service = this.services[name];
results.push(service.removeRoom(jid));
}
await Promise.all(results);
this.contactManager.deleteFromCache(jid.bare);
}
public async load(): Promise<IContact[]> {
let bookmarks = await this.getReducedBookmarksFromServices();
let contacts = [];
for (let id in bookmarks) {
let bookmark = bookmarks[id];
contacts[contacts.length] = this.initBookmarkContact(bookmark.room, bookmark.service);
}
return contacts;
}
private async getReducedBookmarksFromServices(): Promise<{
[id: string]: { room: RoomBookmark; service: AbstractService };
}> {
let bookmarks: {
[id: string]: { room: RoomBookmark; service: AbstractService };
} = {};
for (let name in this.services) {
let service = this.services[name];
let rooms = await service.getRooms();
for (let room of rooms) {
bookmarks[room.getId()] = {
room,
service,
};
}
}
return bookmarks;
}
private initBookmarkContact(bookmark: RoomBookmark, service: AbstractService): IContact {
let contact = this.createContact(bookmark.getJid());
contact.setNickname(bookmark.getNickname());
contact.setPassword(bookmark.getPassword());
contact.setBookmark(true);
contact.setAutoJoin(bookmark.isAutoJoin());
contact.setProvider(this);
if (bookmark.hasAlias()) {
contact.setName(bookmark.getAlias());
}
if (bookmark.isAutoJoin()) {
contact.setRoomConfiguration(ROOMCONFIG.INSTANT);
contact.join();
}
return contact;
}
}