import Account from './Account'; import JID from './JID'; import IStorage from './Storage.interface'; import Client from './Client'; import ClientAvatar from './ClientAvatar'; import RoleAllocator from './RoleAllocator'; import Log from '@util/Log'; import Utils from '@util/Utils'; import * as UI from './ui/web'; export default class AccountManager { private accounts: { [id: string]: Account } = {}; constructor(private storage: IStorage) {} public restoreAccounts(): number { let accountIds = this.getAccountIds(); let pendingAccountIds = this.getPendingAccountIds(); let numberOfAccounts = accountIds.length + pendingAccountIds.length; accountIds.forEach(this.initAccount); pendingAccountIds.forEach(this.initAccount); this.storage.setItem('pendingAccounts', []); this.storage.setItem('accounts', Object.keys(this.accounts)); this.storage.registerHook('accounts', this.accountsHook); return numberOfAccounts; } private initAccount = (id: string) => { if (this.accounts[id]) { Log.debug('destroy old account with uid ' + id); this.accounts[id].destroy(); } let account = (this.accounts[id] = new Account(id)); Client.getPresenceController().registerAccount(account); ClientAvatar.get().registerAccount(account); UI.init(); RoleAllocator.get() .waitUntilMaster() .then(function () { return account.connect(); }) .then(function () {}) .catch(function (msg) { account.connectionDisconnected(); Log.warn(msg); }); }; private accountsHook = (newValue, oldValue) => { let diff = Utils.diffArray(newValue, oldValue); let newAccountIds = diff.newValues; let deletedAccountIds = diff.deletedValues; newAccountIds.forEach(this.initAccount); deletedAccountIds.forEach(id => { let account: Account = this.accounts[id]; if (account) { delete this.accounts[account.getUid()]; account.remove(); } }); }; public createAccount(url: string, jid: string, sid: string, rid: string): Promise; public createAccount(url: string, jid: string, password: string): Promise; public createAccount() { let account: Account; if (!arguments[0]) { return Promise.reject('We need an url to create an account'); } else if (this.getAccount(arguments[1])) { return Promise.reject('Account with this jid already exists.'); } else if (arguments.length === 4) { account = new Account(arguments[0], arguments[1], arguments[2], arguments[3]); } else if (arguments.length === 3) { account = new Account(arguments[0], arguments[1], arguments[2]); } else { return Promise.reject('Wrong number of arguments'); } return Promise.resolve(account); } public getAccount(jid: JID): Account; public getAccount(uid?: string): Account; public getAccount() { let uid; if (arguments[0] instanceof JID) { uid = arguments[0].bare; } else if (arguments[0]) { uid = arguments[0]; } else { uid = Object.keys(this.accounts)[0]; } return this.accounts[uid]; } public getAccounts(): Account[] { // @REVIEW use of Object.values() let accounts = []; for (let id in this.accounts) { accounts.push(this.accounts[id]); } return accounts; } public addAccount(account: Account) { if (this.getAccount(account.getUid())) { throw new Error('Account with this jid already exists.'); } this.accounts[account.getUid()] = account; this.storage.setItem('accounts', Object.keys(this.accounts)); } private getAccountIds(): string[] { return this.storage.getItem('accounts') || []; } public addPendingAccount(account: Account) { let uid = account.getUid(); let pendingAccounts = this.getPendingAccountIds(); if (pendingAccounts.indexOf(uid) < 0) { pendingAccounts.push(uid); this.storage.setItem('pendingAccounts', pendingAccounts); } } private getPendingAccountIds(): string[] { return this.storage.getItem('pendingAccounts') || []; } public removeAccount(account: Account) { let ids = Object.keys(this.accounts).filter(id => id !== account.getUid()); this.storage.setItem('accounts', ids); if (ids.length === 0) { Client.getNoticeManager().removeAll(); } } }