src/calls/CallLog.js
import Logs from '../Logs';
import {EventEmitter} from '../eventemitter';
import {bindMethods} from '../utils/bindMethods';
import {CallDirection} from './CallDirection';
import {getEndReasonFromWacValue} from './CallEndReason';
import {CallLogEntry} from './CallLogEntry';
import {CallStatus} from './CallStatus';
const log = Logs.instance.getLogger('SippoJS/CallLog');
/**
* Manages the contacts and groups which they belongs to
* CallLogManager instance is obtained by calling the {Session#getCallLogManager} method
*/
export class CallLog {
/**
* @protected
*/
static create(callService, userManager) {
const callLog = new CallLog(callService, userManager);
return callLog.fetch().then(() => callLog);
}
/**
* @private
*/
constructor(callService, userManager) {
/** @private */
this.callService = callService;
/** @private */
this.userManager = userManager;
/** @private */
this.entries = [];
/** @private */
this.lastEntryRecovered = false;
/**
* Emits the next possible events:
* - "update" event every time an existing entry is updated
* - "create" event every time a new entry is prepended
* - "fetch" event every time more entries are appended
* @type {EventEmitter}
*/
this.emitter = new EventEmitter();
bindMethods(this, [
'onUpdate',
]);
this.bindEventHandlers();
}
/**
* @private
*/
bindEventHandlers() {
this.callService.emitter.on('updated', this.onUpdate);
this.callService.emitter.on('created', this.onUpdate);
}
/**
* Fetch more callLog entries
* @param {number} [limit=20] The number of new entries to be fetched at most
* @return {Promise} When resolved, the update was completed
*/
fetch(limit = 20) {
if (this.lastEntryRecovered) {
return;
}
return this.callService.get({limit, sortBy: 'from'}).then((data) => {
if (data.length <= 0) {
this.lastEntryRecovered = true;
return;
}
this.lastEntryRecovered = true; // Hack until lastRecoveredTimestamp is used
this.lastRecoveredTimestamp = data[data.length - 1].from;
const callLogs = data.map(datum => this.createCallLogEntry(datum));
this.entries = [...this.entries, ...callLogs];
this.emitter.emit('fetch');
});
}
/**
* Obtains the list with the available CallLog items
* @return {CallLog[]}
*/
getEntries() {
return this.entries;
}
/**
* Retrieves a CallLog by given its ID
* @param {String} id
* @return {CallLog}
*/
getById(id) {
return this.entries.find(callLog => callLog.id === id);
}
/**
* @private
*/
calculateStatus(status) {
switch (status) {
case 'active':
return CallStatus.CONNECTED;
case 'routed':
return CallStatus.TRYING;
case 'finished':
return CallStatus.DISCONNECTED;
default:
log.error(`Unexpected status: ${status}`);
}
}
/**
* @private
*/
createCallLogEntry(datum) {
const status = this.calculateStatus(datum.state);
const endReason = getEndReasonFromWacValue(datum.endReason);
const direction = this.userManager.isOwnAddress(datum.caller) ?
CallDirection.OUTGOING : CallDirection.INCOMING;
return new CallLogEntry(
datum.id,
datum.callee,
datum.caller,
datum.target || datum.callee,
new Date(datum.from),
new Date(datum.to),
status,
endReason,
direction,
datum.origin,
datum.data,
);
}
/**
* @private
*/
onUpdate(callLogDatum) {
const newEntry = this.createCallLogEntry(callLogDatum);
const oldEntry = this.entries.find(entry => entry.id === callLogDatum.id);
if (oldEntry) {
this.entries = this.entries.map(entry => entry.getId() === callLogDatum.id ? newEntry : entry);
this.emitter.emit('update', newEntry, oldEntry);
} else {
this.entries = [newEntry, ...this.entries];
this.emitter.emit('create', newEntry);
}
}
}