Home Reference Source

src/contacts/Presence.js

import Logs from '../Logs';
import {EventEmitter} from '../eventemitter';
import {bindMethods} from '../utils/bindMethods';

import {PresenceActivity} from './PresenceActivity';
import {PresenceMood} from './PresenceMood';

const log = Logs.instance.getLogger('SippoJS/Presence');

/**
 * This class must not be instantiated. Presence objects are automatically obtained
 * associated to {@link Contact} objects.
 *
 * ## Events
 *
 * - **`update`** -> triggered every time the presence object is updated.
 */
export class Presence extends EventEmitter {

	/**
	 * Represents the different status of an user
	 * @type {Enum<PresenceActivity>}
	 * @deprecated Use "import {PresenceActivity} from '@quobis/sippojs' instead"
	 */
	get ACTIVITY() {
		log.warn('Presence.ACTIVITY is deprecated. Please use import {PresenceActivity} from "@quobis/sippojs" instead');
		return PresenceActivity;
	}

	/**
	 * Represents the different emotional states of an user
	 * @type {Enum<PresenceMood>}
	 * @deprecated Use "import {PresenceMood} from '@quobis/sippojs' instead"
	 */
	get MOOD() {
		log.warn('Presence.MOOD is deprecated. Please use import {PresenceMood} from "@quobis/sippojs" instead');
		return PresenceMood;
	}

	/**
	 * @param {PresenceManager} presenceManager
	 * @param {string} address
	 */
	constructor(presenceManager, address) {
		super();
		/**
		 * @type {PresenceManager}
		 */
		this._presenceManager = presenceManager;

		/**
		 * @type {boolean}
		 */
		this._online = false;

		/**
		 * @type {PresenceActivity}
		 */
		this._activity = PresenceActivity.unknown;

		/**
		 * @type {PresenceMood}
		 */
		this._mood = PresenceMood.unknown;

		/**
		 * @type {String}
		 */
		this._note = '';

		/**
		 * @type {string}
		 */
		this._avatar = '';

		/**
		 * @type {string}
		 */
		this._displayName = '';

		bindMethods(this, [
			'onPresenceUpdated',
		]);
		if (!address) {
			this._initializing = Promise.resolve();
		}
		this.address = address;
	}

	/**
	 * Address associated with this presence
	 * @type {String}
	 */
	get address() {
		return this._address;
	}

	/**
	 * Update address associated with this presence
	 * @type {String}
	 */
	set address(address) {
		if (this._address === address) {
			return;
		}
		if (this._address) {
			this._presenceManager.unsubscribeFromPresence(this._address);
			this._presenceManager.emitter.off('updated', this.onPresenceUpdated);
			this.update({
				online: false,
				activity: 'unknown',
				mood: 'unknown',
				note: '',
				avatar: '',
				displayName: '',
				address: '',
			});
		}
		this._address = address;
		if (this._address) {
			this._initializing = this._presenceManager.subscribeToPresence(this._address);
			this._initializing.then((presence) => {
				this.update(presence);
			});
			this._presenceManager.emitter.on('updated', this.onPresenceUpdated);
		}

	}

	/**
	 * User is online
	 * @type {boolean}
	 */
	get online() {
		return this._online;
	}

	/**
	 * User activity
	 * @type {PresenceActivity}
	 */
	get activity() {
		return this._activity;
	}

	/**
	 * User emotional state
	 * @type {PresenceMood}
	 */
	get mood() {
		return this._mood;
	}

	/**
	 * Short message defined by user
	 * @type {String}
	 */
	get note() {
		return this._note;
	}

	/**
	 * Avatar location
	 * @type {String}
	 */
	get avatar() {
		return this._avatar;
	}

	/**
	 * Display name
	 * @type {String}
	 */
	get displayName() {
		return this._displayName;
	}

	/**
	 * @return {Promise<void>}
	 */
	waitUntilSynced() {
		return this._initializing;
	}

	/**
	 * Callback called when a presence update is received
	 * @private
	 * @param {Presence} presence new presence received
	 */
	onPresenceUpdated(presence) {
		if (presence.address === this._address) {
			this.update(presence);
		}
	}

	/**
	 * Updates the presence with new data
	 * @protected
	 * @param {Object} data
	 * @param {boolean} data.online
	 * @param {string} data.activity
	 * @param {string} data.mood
	 * @param {string} data.note
	 * @param {string} data.avatar
	 * @param {string} data.displayName
	 */
	update(data) {
		this._online = data.online;
		this._activity = PresenceActivity[data.activity];
		this._mood = PresenceMood[data.mood];
		this._note = data.note;
		this._avatar = data.avatar;
		this._displayName = data.displayName;
		this._address = data.address;
		this.emit('update');
	}

	/**
	 * Returns a JSON representation of the object.
	 * @return {Object}
	 * @property {boolean} online
	 * @property {string} activity
	 * @property {string} mood
	 * @property {string} note
	 * @property {string} avatar
	 * @property {string} displayName
	 */
	toJSON() {
		return {
			address: this._address,
			online: this._online,
			activity: PresenceActivity[this._activity],
			mood: PresenceMood[this._mood],
			note: this._note,
			avatar: this._avatar,
			displayName: this._displayName,
		};
	}
}