Created
March 30, 2016 15:27
-
-
Save fmquaglia/ab59dc5fb32f58dcf31d65fc7b5cc643 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
angular.module('circleBackApp') | |
.service('Contacts', function($rootScope, $http, $localStorage, $log, $q, $filter, $timeout, CBCore, AuthService, Sorting, Groups) { | |
var Contacts = {}; | |
Contacts.byId = {}; // contactId: Contact | |
Contacts.byGroupId = {}; // groupId: {contactId: Contact} LIVE contacts only | |
Contacts.groupsByContactId = {}; // contactId: {id: group} | |
Contacts.trashById = {}; // contactId: Contact | |
Contacts.headerById = {}; | |
Contacts.canonicalNameById = {}; | |
// Private utility functions | |
/** | |
* Applies a function to all cached contacts, trash and live. | |
* @param fnToApply the function to apply. | |
*/ | |
function applyFnToAllCachedContacts(fnToApply) { | |
if (angular.isFunction(fnToApply)) { | |
angular.forEach(Contacts.byId, fnToApply); | |
angular.forEach(Contacts.trashById, fnToApply); | |
} | |
} | |
/** | |
* Updates the local group indexes for a contact. | |
* @param contactId the contact to update | |
* @param added added group ID list | |
* @param removed removed group ID list | |
*/ | |
function updateGroupIndexes(contactId, added, removed) { | |
// Removed | |
angular.forEach(removed, function(groupId) { | |
delete Contacts.byGroupId[groupId][contactId]; | |
if (Contacts.groupsByContactId[contactId]) { | |
delete Contacts.groupsByContactId[contactId][groupId]; | |
} | |
}); | |
// Added | |
if (added) { | |
var contact = Contacts.byId[contactId]; | |
if (angular.isObject(contact)) { | |
angular.forEach(added, function(groupId) { | |
if (angular.isUndefined(groupId)) { | |
throw new Error("Null group ID"); | |
} | |
// Make sure the objects we need exist | |
if (angular.isUndefined(Contacts.byGroupId[groupId])) { | |
Contacts.byGroupId[groupId] = {}; | |
} | |
if (angular.isUndefined(Contacts.groupsByContactId[contactId])) { | |
Contacts.groupsByContactId[contactId] = {}; | |
} | |
// Update them | |
Contacts.byGroupId[groupId][contactId] = contact; | |
Contacts.groupsByContactId[contactId][groupId] = Groups.getById(groupId); | |
}); | |
} | |
} | |
} | |
/** | |
* Moves a cached contact between two objects. | |
* @param contactId the contact id. | |
* @param src source object | |
* @param dst destination object | |
*/ | |
function moveCachedContact(contactId, src, dst) { | |
var contact = src[contactId]; | |
delete src[contactId]; | |
dst[contactId] = contact; | |
} | |
/** | |
* Saves a contact in local storage. | |
* @param newContact the contact to save. | |
*/ | |
function updateCachedContact(newContact, contactsByIdObject) { | |
var oldContact; | |
if (angular.isDefined(contactsByIdObject)) { | |
oldContact = contactsByIdObject[newContact.contactId]; | |
} else { | |
// Look in the live contacts list for the contact | |
oldContact = Contacts.byId[newContact.contactId] || Contacts.trashById[newContact.contactId]; | |
} | |
// Update our cached strings | |
updateCachedStrings(newContact); | |
// Add (or update, maintaining the contact object references) | |
if (newContact !== oldContact) { | |
if (angular.isUndefined(oldContact)) { | |
contactsByIdObject[newContact.contactId] = newContact; | |
// Update groups indexes | |
updateGroupIndexes(newContact.contactId, Contacts.getGroupIds(newContact), []); | |
} else { | |
// Update groups indexes | |
var groupDiff = Contacts.diffGroups(newContact, oldContact); | |
updateGroupIndexes(newContact.contactId, groupDiff.added, groupDiff.removed); | |
// Clear the old keys | |
angular.forEach(_.keys(oldContact), function(key) { | |
delete oldContact[key]; | |
}); | |
// Copy the data into the old object | |
angular.copy(newContact, oldContact); | |
} | |
} | |
} | |
/** | |
* Caches the header and sorting strings for each contact | |
* @param contact | |
*/ | |
function updateCachedStrings(contact) { | |
Contacts.headerById[contact.contactId] = Sorting.getSectionHeader(contact); | |
Contacts.canonicalNameById[contact.contactId] = Sorting.getCanonicalName(contact); | |
} | |
/** | |
* Removes a contact from local storage | |
* @param contactId the ID of the contact to remove from local storage. | |
*/ | |
function removeCachedContact(contactId, contactsByIdObject) { | |
delete contactsByIdObject[contactId]; | |
delete Contacts.imageByContactId[contactId]; | |
// Remove all group indexes | |
if (angular.isObject(Contacts.groupsByContactId[contactId])) { | |
angular.forEach(_.keys(Contacts.groupsByContactId[contactId]), function(groupId) { | |
delete Contacts.byGroupId[groupId][contactId]; | |
delete Contacts.groupsByContactId[contactId][groupId]; | |
}); | |
} | |
// Remove cached strings | |
delete Contacts.headerById[contactId]; | |
delete Contacts.canonicalNameById[contactId]; | |
} | |
/** | |
* Removes a group from a cached contact and group indexes. | |
* @param contactId the contact ID | |
* @param groupIdToRemove the group ID | |
*/ | |
function removeGroupFromCachedContact(contact, groupIdToRemove) { | |
if (angular.isObject(contact) && angular.isArray(contact.groups)) { | |
contact.groups = _.without(contact.groups, function(group) { | |
group.id = groupIdToRemove; | |
}); | |
} | |
updateGroupIndexes(contactId, [], [groupIdToRemove]); | |
} | |
/** | |
* Adds and removes groups for a cached contact. | |
* @param contactId the contact ID | |
* @param added array of group IDs to add. | |
* @param removed array of group IDs to remove. | |
*/ | |
function assignCachedContactGroups(contactId, added, removed) { | |
var contact = Contacts.getContact(contactId); | |
// Remove groups | |
angular.forEach(removed, function(groupId) { | |
for(var i = 0; i < contact.groups.length; i++) { | |
if (angular.isObject(contact.groups[i]) && contact.groups[i].id == groupId) { | |
contact.groups.splice(i, 1); | |
break; | |
} | |
} | |
}); | |
// Add groups | |
angular.forEach(added, function(groupId) { | |
var group = Groups.getById(groupId); | |
contact.groups.push({ | |
id: group.groupId, | |
name: group.name, | |
type: group.type | |
}); | |
}); | |
updateGroupIndexes(contactId, added, removed) | |
} | |
function isContactInMap(contactId, contactsByIdObject) { | |
return angular.isDefined(contactsByIdObject[contactId]); | |
} | |
// Utility methods | |
/** | |
* Updates an object to add missing and remove old contacts. | |
* @param map the object, indexed by contact ID. | |
* @param newContactIds the new contact IDs to be contained in the map. | |
*/ | |
Contacts.updateContactIdMap = function (map, newContactIds) { | |
var currentContactIds = _.keys(map); | |
// Delete any old IDs | |
var idsToDelete = _.difference(currentContactIds, newContactIds); | |
angular.forEach(idsToDelete, function(contactIdToDelete) { | |
delete map[contactIdToDelete]; | |
}); | |
// Add any new IDs | |
var idsToAdd = _.difference(newContactIds, currentContactIds); | |
angular.forEach(idsToAdd, function(contactIdToAdd) { | |
map[contactIdToAdd] = Contacts.getContact(contactIdToAdd); | |
}); | |
}; | |
/** | |
* Gets the size of a contacts object. | |
* @param contactsByIdObject | |
* @returns {*number} the size, or zero if not an object. | |
*/ | |
Contacts.size = function(contactsByIdObject) { | |
if (angular.isObject(contactsByIdObject)) { | |
return _.size(contactsByIdObject); | |
} | |
return 0; | |
}; | |
Contacts.countByGroupId = function(groupId) { | |
if (Contacts.byGroupId[groupId]) { | |
return _.size(Contacts.byGroupId[groupId]); | |
} else { | |
return 0; | |
} | |
} | |
// Contact list | |
/** | |
* Fetches contacts and saves them in local storage. | |
* @private | |
* @param trash {boolean} false to get live contacts, true to get trashed ones | |
* @param since {int} the last time the list was fetched. | |
*/ | |
function fetchContacts(trash, since) { | |
$log.log("Contacts:fetchContacts(trash, since)", trash, since); | |
var deferred = $q.defer(); | |
$http.get(CBCore.coreConfig.contacts, {params: {viewTrash: trash, changesAsOfTicks: since, _nocache: new Date().getTime()}}) | |
.success(function(response, status, headers, config) { | |
if (angular.isArray(response.contactList)) { | |
Contacts.setContacts(response.contactList, trash); | |
// Remove deleted contacts | |
angular.forEach(response.deletedContactIds, function(contactId) { | |
if (trash) { | |
removeCachedContact(contactId, Contacts.trashById); | |
} else { | |
removeCachedContact(contactId, Contacts.byId); | |
} | |
}); | |
$rootScope.$broadcast('Contacts.fetchContacts', response.contactList.length); | |
deferred.resolve(response); | |
} else { | |
// TODO: Handle responses intelligently. What are the possible errors? | |
deferred.reject("Unexpected response from server."); | |
} | |
}) | |
.error(function(data, status, headers, config) { | |
// TODO: Handle responses intelligently. What are the possible errors? | |
deferred.reject(status); | |
} | |
); | |
return deferred.promise; | |
} | |
function filterContacts(filter, key, contacts) { | |
var filteredContacts = $filter(filter)(contacts, key); | |
return filteredContacts; | |
} | |
/** | |
* Sorts and filters a list of contacts by the current group an search filters. | |
* @param list of contact ids to sort and filter | |
*/ | |
Contacts.getFilteredContactList = function(contactIdList, searchTerm) { | |
$log.log("Contacts.getFilteredContactList(contactIdList.length, searchTerm)", contactIdList.length, searchTerm); | |
// Get an array of contacts | |
var contacts = _.chain(contactIdList) | |
.map(Contacts.getContact) | |
.compact() | |
.value(); | |
// Apply the search filter | |
if (searchTerm) { | |
contacts = filterContacts('contactsFilter', searchTerm, contacts); | |
} | |
return contacts; | |
}; | |
var lastRefresh = 0; | |
var lastTrashRefresh = 0; | |
Contacts.promise = null; | |
Contacts.refreshContacts = function() { | |
$log.log('Contacts.refreshContacts'); | |
Contacts.promise = $q.all([fetchContacts(false, lastRefresh), fetchContacts(true, lastTrashRefresh)]) | |
.then(function(responses) { | |
lastRefresh = responses[0].queryDetails.currentServerTime; | |
lastTrashRefresh = responses[1].queryDetails.currentServerTime; | |
}, function(status) { | |
$log.log("Failed to refresh contacts", status); | |
}); | |
return Contacts.promise; | |
}; | |
/** | |
* Set contacts from a list. | |
* @param contactList the list of contacts | |
* @param trash true if the contacts are going in the trash | |
*/ | |
Contacts.setContacts = function(contactList, trash) { | |
// Update the cached contacts | |
angular.forEach(contactList, function(contact) { | |
if (angular.isUndefined(contact)) { | |
throw new Error("Undefined contact in contact list."); | |
} | |
// Move the contact to the proper list to maintain the object reference, then update it | |
if (trash) { | |
if (isContactInMap(contact.contactId, Contacts.byId)) { | |
moveCachedContact(contact.contactId, Contacts.byId, Contacts.trashById); | |
} | |
updateCachedContact(contact, Contacts.trashById); | |
} else { | |
if (isContactInMap(contact.contactId, Contacts.trashById)) { | |
moveCachedContact(contact.contactId, Contacts.trashById, Contacts.byId); | |
} | |
updateCachedContact(contact, Contacts.byId); | |
} | |
}); | |
}; | |
/** | |
* Gets the time of the last successful refresh. | |
* @returns {number} | |
*/ | |
Contacts.getLastRefresh = function() { | |
return lastRefresh; | |
}; | |
// Individual contacts | |
Contacts.getHeader = function(contactId) { | |
return Contacts.headerById[contactId]; | |
}; | |
/** | |
* Gets a list of groupIds from a contact. | |
* @param contact the contact | |
* @returns {Array} | |
*/ | |
Contacts.getGroupIds = function(contact) { | |
if (angular.isUndefined(contact)) { | |
throw new Error("contact is undefined."); | |
} | |
return _.chain(contact.groups).map(function(group) { | |
return group.id; | |
}).compact().value(); | |
}; | |
/** | |
* Gets a map of added and removed group IDs. | |
* @param newGroupIds new group ID list. | |
* @param oldGroupIds old group ID list. | |
* @returns {{added: (*|Array), removed: (*|Array)}} | |
*/ | |
Contacts.diffGroupIds = function(newGroupIds, oldGroupIds) { | |
var addedGroupIds = _.difference(newGroupIds, oldGroupIds); | |
var removedGroupIds = _.difference(oldGroupIds, newGroupIds); | |
return { | |
"added": _.compact(addedGroupIds), // HACK: Group IDs can be blank. | |
"removed": _.compact(removedGroupIds) // HACK: Group IDs can be blank. | |
}; | |
}; | |
/** | |
* Gets a map of added and removed group IDs. | |
*/ | |
Contacts.diffGroups = function(newContact, oldContact) { | |
var newGroupIds = Contacts.getGroupIds(newContact); | |
var oldGroupIds = angular.isDefined(oldContact) ? | |
Contacts.getGroupIds(oldContact) : | |
[]; | |
return Contacts.diffGroupIds(newGroupIds, oldGroupIds); | |
}; | |
/** | |
* Assigns and removes contacts to groups. | |
* @param contactIds list of contact IDs. | |
* @param groupIdsToAdd list of group IDs. | |
* @param groupIdsToRemove list of group IDs. | |
* @returns {Promise.promise|*} | |
*/ | |
Contacts.assignContactGroups = function(contactIds, groupIdsToAdd, groupIdsToRemove) { | |
var deferred = $q.defer(); | |
// filter sigcapture groups | |
groupIdsToAdd = $filter('rejectSigCaptureGroups')(groupIdsToAdd); | |
groupIdsToRemove = $filter('rejectSigCaptureGroups')(groupIdsToRemove); | |
// Stop now if there's nothing to do | |
if (groupIdsToAdd.length == 0 && groupIdsToRemove.length == 0) { | |
deferred.resolve(); | |
return deferred.promise; | |
} | |
CBCore.groups.assign( | |
{ | |
"assign": { | |
groups: groupIdsToAdd, | |
contacts: contactIds | |
}, | |
"remove": { | |
groups: groupIdsToRemove, | |
contacts: contactIds | |
} | |
}, | |
function(response) { | |
// NOTE: Refetching the contact immediately can return stale data, handle the update locally | |
angular.forEach(contactIds, function(contactId) { | |
assignCachedContactGroups(contactId, groupIdsToAdd, groupIdsToRemove); | |
}); | |
deferred.resolve(); | |
$rootScope.$broadcast('Contacts.contact.groups.assign', contactIds); | |
}, | |
function(status, data) { | |
deferred.reject(status); | |
}); | |
return deferred.promise; | |
}; | |
/** | |
* Adds the contact to a group. | |
* @param contactIds | |
* @param groupToAdd the group object | |
* @returns {Promise.promise|*} | |
*/ | |
Contacts.addContactToGroup = function(contactIds, groupToAdd) { | |
$log.log('Contacts.addContactToGroup', contactIds, groupToAdd.name); | |
var deferred = $q.defer(); | |
if (angular.isString(contactIds)) { | |
contactIds = [contactIds]; | |
} | |
// Make sure we have some contacts to update | |
if (!angular.isArray(contactIds) || contactIds.length == 0) { | |
return; | |
} | |
CBCore.groups.assign( | |
{ | |
'assign': { | |
'groups': [groupToAdd.groupId], | |
'contacts': contactIds | |
} | |
}, | |
function(response) { | |
// FYI: Refetching the contact immediately can return stale data, handle the update locally | |
_.each(contactIds, function(contactId) { | |
var contact = Contacts.getContact(contactId); | |
// Skip bad contacts | |
if (!angular.isObject(contact)) { | |
return; | |
} | |
// Add the groups array if the contact doesn't have on yet | |
if (!angular.isArray(contact.groups)) { | |
contact.groups = []; | |
} | |
// Skip this contact if it already has the group | |
if (_.some(contact.groups, function(group) {return group.name == groupToAdd.name})) { | |
return; | |
} | |
// Add the group | |
contact.groups.push({ | |
id: groupToAdd.groupId, | |
name: groupToAdd.name, | |
type: groupToAdd.type | |
}); | |
// Update the contact | |
assignCachedContactGroups(contactId, [groupToAdd.groupId], []); | |
deferred.resolve(); | |
}); | |
$rootScope.$broadcast('Contacts.contact.groups.assign', contactIds); | |
}, | |
function(status, data) { | |
deferred.reject(status); | |
}); | |
return deferred.promise; | |
}; | |
/** | |
* Removes the contact from a group. | |
* @param contactIds | |
* @param groupToRemove the group object | |
* @returns {Promise.promise|*} | |
*/ | |
Contacts.removeContactFromGroup = function(contactIds, groupToRemove) { | |
$log.log('Contacts.removeContactFromGroup', contactIds, groupToRemove.name); | |
var deferred = $q.defer(); | |
if (angular.isString(contactIds)) { | |
contactIds = [contactIds]; | |
} | |
// Make sure we have some contacts to update | |
if (!angular.isArray(contactIds) || contactIds.length == 0) { | |
return; | |
} | |
CBCore.groups.assign( | |
{ | |
'remove': { | |
'groups': [groupToRemove.groupId], | |
'contacts': contactIds | |
} | |
}, | |
function(response) { | |
angular.forEach(contactIds, function(contactId) { | |
assignCachedContactGroups(contactId, [], [groupToRemove.groupId]); | |
}); | |
$rootScope.$broadcast('Contacts.contact.groups.assign', contactIds); | |
deferred.resolve(); | |
}, | |
function(status, data) { | |
deferred.reject(status); | |
}); | |
return deferred.promise; | |
}; | |
/** | |
* Determines if a contact is in the trash. | |
* @param contactId the contact ID | |
* @returns {boolean} true if the contact is in the trashContactIdList. | |
*/ | |
Contacts.isTrash = function(contactId) { | |
return angular.isObject(Contacts.trashById[contactId]); | |
}; | |
/** | |
* Fetches a single contact and saves it in local storage. | |
* @param contactId the contact ID to fetch. | |
* @returns {Promise.promise|*} | |
*/ | |
Contacts.fetchContact = function(contactId) { | |
$log.log("Contacts.fetchContact", contactId); | |
var deferred = $q.defer(); | |
if (!angular.isDefined(contactId) || contactId == null) { | |
throw new Error("contactId must not be null"); | |
} | |
// Fetch the contacts | |
CBCore.contacts.get({contactId: contactId}, | |
// Success handler | |
function(result) { | |
if (result.contact) { | |
updateCachedContact(result.contact, Contacts.byId); | |
deferred.resolve(result.contact); | |
} else { | |
// TODO: Handle responses intelligently. What are the possible errors? | |
deferred.reject("Unexpected response from server."); | |
} | |
}, | |
// Error handler | |
function(status, data) { | |
// TODO: Handle responses intelligently. What are the possible errors? | |
deferred.reject(status); | |
}); | |
return deferred.promise; | |
}; | |
/** | |
* Fetches an array of contacts | |
* @param contactIds | |
* @returns {Promise.promise|*} | |
*/ | |
Contacts.fetchContacts = function(contactIds) { | |
var promises = []; | |
angular.forEach(contactIds, function(contactId) { | |
var promise = Contacts.fetchContact(contactId); | |
promises.push(promise); | |
}); | |
return $q.all(promises); | |
}; | |
/** | |
* Gets a contact from local storage. | |
* @param contactId the contact to get. | |
* @returns {*} the contact. | |
*/ | |
Contacts.getContact = function(contactId) { | |
return Contacts.byId[contactId] || Contacts.trashById[contactId]; | |
}; | |
/** | |
* Creates a contact. | |
* @param contact the contact to create. | |
* @returns {Promise.promise|*} | |
*/ | |
Contacts.createContact = function(contact) { | |
var deferred = $q.defer(); | |
var contact = new CBCore.contacts(contact); | |
var extId = new Date().getTime().toString(); | |
contact.externalSourceInfo = {sourceContext: "WebSync", externalSourceId: extId}; | |
contact.$save( | |
function(response) { | |
// Check for errors | |
if (!angular.isObject(response.contact) || responseHasErrors(response)) { | |
deferred.reject(response); | |
return; | |
} | |
// Add the contact to local storage | |
updateCachedContact(response.contact, Contacts.byId); | |
$rootScope.$broadcast('Contacts.createContact', response); | |
deferred.resolve(response.contact); | |
}, | |
function(status, data) { | |
deferred.reject(status); | |
return status; | |
}); | |
return deferred.promise; | |
}; | |
/** | |
* Gets a Contact's canonical name. | |
* @param contact or contactId | |
* @returns {*} | |
*/ | |
Contacts.getCanonicalName = function(contact) { | |
if (angular.isObject(contact)) { | |
return Contacts.canonicalNameById[contact.contactId] || ''; | |
} else { | |
return Contacts.canonicalNameById(contact) || ''; // contactId | |
} | |
}; | |
function responseHasErrors(response) { | |
return angular.isDefined(response.errors) || | |
angular.isDefined(response.errorMessage) || | |
angular.isDefined(response.errorCode); | |
} | |
/** | |
* Updates a contact. | |
* @param contact the contact to update. | |
* @returns {Promise.promise|*} | |
*/ | |
Contacts.updateContact = function(contact) { | |
var deferred = $q.defer(); | |
var contact = new CBCore.contacts(contact); | |
contact.$update( | |
function(response) { | |
// Check for errors | |
if (!angular.isObject(response.contact) || responseHasErrors(response)) { | |
deferred.reject(response); | |
return; | |
} | |
updateCachedContact(response.contact); | |
$rootScope.$broadcast('Contacts.updateContact', response); | |
deferred.resolve(response.contact); | |
}, | |
function(status, data) { | |
deferred.reject(status); | |
return status; | |
}); | |
return deferred.promise; | |
}; | |
Contacts.trash = function(contactIdsToTrash) { | |
var deferred = $q.defer(); | |
if (!angular.isArray(contactIdsToTrash)) { | |
contactIdsToTrash = [contactIdsToTrash]; | |
} | |
CBCore.contacts.bulkDelete( | |
{idList: contactIdsToTrash}, | |
function(response) { | |
angular.forEach(contactIdsToTrash, function(contactId) { | |
moveCachedContact(contactId, Contacts.byId, Contacts.trashById); | |
updateGroupIndexes(contactId, [], Contacts.getGroupIds(Contacts.getContact(contactId))); | |
}); | |
deferred.resolve(contactIdsToTrash); | |
$rootScope.$broadcast('Contacts.trash', contactIdsToTrash); | |
}, | |
function(status, data) { | |
deferred.reject(status); | |
} | |
); | |
return deferred.promise; | |
}; | |
Contacts.purge = function(contactIdsToPurge) { | |
var deferred = $q.defer(); | |
if (!angular.isArray(contactIdsToPurge)) { | |
contactIdsToPurge = [contactIdsToPurge]; | |
} | |
CBCore.contacts.bulkDelete( | |
{ 'purgeContacts': true, 'idList': contactIdsToPurge }, | |
function(response) { | |
angular.forEach(contactIdsToPurge, function(contactId) { | |
removeCachedContact(contactId, Contacts.trashById); | |
}); | |
deferred.resolve(contactIdsToPurge); | |
$rootScope.$broadcast("Contacts.purge", contactIdsToPurge); | |
}, | |
function(status, data) { | |
deferred.reject(status); | |
}); | |
return deferred.promise; | |
}; | |
Contacts.restore = function(contactIdsToRestore) { | |
var deferred = $q.defer(); | |
if (!angular.isArray(contactIdsToRestore)) { | |
contactIdsToRestore = [contactIdsToRestore]; | |
} | |
CBCore.contacts.restore( | |
{'idList': contactIdsToRestore}, | |
function(response) { | |
angular.forEach(contactIdsToRestore, function(contactId) { | |
moveCachedContact(contactId, Contacts.trashById, Contacts.byId); | |
updateGroupIndexes(contactId, Contacts.getGroupIds(Contacts.getContact(contactId)), []); | |
}); | |
deferred.resolve(contactIdsToRestore); | |
$rootScope.$broadcast("Contacts.restore", contactIdsToRestore); | |
}, | |
function(status, data) { | |
deferred.reject(status); | |
}); | |
return deferred.promise; | |
}; | |
// Create byGroupId object when a group is created | |
$rootScope.$on('Groups.create', function(event, group) { | |
if (angular.isUndefined(Contacts.byGroupId[group.groupId])) { | |
Contacts.byGroupId[group.groupId] = {} | |
} | |
}); | |
// Update local contacts when a group is deleted | |
$rootScope.$on('Groups.delete', function(event, group) { | |
applyFnToAllCachedContacts(function(contact, contactId) { | |
removeGroupFromCachedContact(contact, group.groupId) | |
}); | |
}); | |
// Update local contacts when a group is renamed | |
$rootScope.$on('Groups.update', function(event, newGroup, oldGroup) { | |
applyFnToAllCachedContacts(function(contact, contactId) { | |
// Skip bad contacts | |
if (angular.isObject(contact)) { | |
// TODO: Use the canonical groups directly in the contacts | |
// Update the group's name | |
if (angular.isArray(contact.groups)) { | |
_.each(contact.groups, function(existingGroup) { | |
if (existingGroup.name == oldGroup.name) { | |
existingGroup.name = newGroup.name; | |
} | |
}); | |
} | |
} | |
}); | |
}); | |
// Contact image URL by contact ID | |
Contacts.imageByContactId = $localStorage['contactImageByContactId'] || {}; | |
if (!angular.isObject(Contacts.imageByContactId)) { | |
Contacts.imageByContactId = {}; | |
$localStorage['contactImageByContactId'] = Contacts.imageByContactId; | |
} | |
/** | |
* Contact images stored as: Contacts.images[contactId][type][size] = url | |
*/ | |
Contacts.images = $localStorage['contactImages']; | |
if (!angular.isObject(Contacts.images)) { | |
Contacts.images = {}; | |
$localStorage['contactImages'] = Contacts.images; | |
} | |
/** | |
* Fetches the Contacts Images since the last time they were requested | |
* @returns {Promise.promise|*} | |
*/ | |
var imagesSince = 0; | |
Contacts.refreshImages = function() { | |
$log.log('Contact.refreshImages'); | |
var deferred = $q.defer(); | |
$http.get(CBCore.coreConfig.contactImages, {params: {updatedSince: imagesSince, _nocache: new Date().getTime()}}) | |
.success(function(response) { | |
if (response) { | |
if(response.currentServerTime) { | |
imagesSince = parseInt(response.currentServerTime, 10); | |
} | |
if (response.contactImages && angular.isArray(response.contactImages)) { | |
// Store images by contactId.type.size | |
_.each(response.contactImages, function(contactImage) { | |
// Skip unavailable images | |
if (contactImage.available !== true) { | |
return; | |
} | |
// Look for and cache contact profile images | |
if (contactImage.typeOfImage == 'ContactProfile' && contactImage.imageSize == 'Large') { | |
Contacts.imageByContactId[contactImage.contactId] = contactImage.accessUrl; | |
} | |
// Contact | |
var contact = Contacts.images[contactImage.contactId]; | |
if (contact == null) { | |
contact = {}; | |
Contacts.images[contactImage.contactId] = contact; | |
} | |
// Type | |
var type = contact[contactImage.typeOfImage]; | |
if (type == null) { | |
type = {}; | |
contact[contactImage.typeOfImage] = type; | |
} | |
// Size | |
type[contactImage.imageSize] = contactImage.accessUrl; | |
}); | |
$localStorage.contactImages = Contacts.images; | |
} | |
} | |
deferred.resolve(); | |
}) | |
.error(function(data, status) { | |
$log.log('Contacts.refreshImages error', data, status); | |
deferred.reject(status); | |
}); | |
return deferred.promise; | |
}; | |
/** | |
* Fetches all the images for a contact. | |
*/ | |
Contacts.fetchAllImagesForContact = function(contactId) { | |
$log.log('Contacts.fetchAllImagesForContact', contactId); | |
var deferred = $q.defer(); | |
CBCore.allImagesForContact.get({contactId: contactId}, | |
function(response) { | |
if (response.contactImages && angular.isArray(response.contactImages)) { | |
deferred.resolve(response.contactImages); | |
} else { | |
deferred.reject(response); | |
} | |
}, function(data, status) { | |
deferred.reject(status); | |
}); | |
return deferred.promise; | |
} | |
/** | |
* Clear the status. | |
*/ | |
Contacts.clear = function() { | |
if (!AuthService.currentAuthInfo) { | |
$log.log("Contacts service logout"); | |
// Delete contacts from local storage | |
_.each(Contacts.list, removeCachedContact); | |
// Clear contacts | |
Contacts.trashById = {}; | |
Contacts.byId = {}; | |
Contacts.byGroupId = {}; | |
Contacts.groupsByContactId = {}; | |
Contacts.images = []; | |
$localStorage.contactImages = []; | |
// Reset the lastRefreshes | |
imagesSince = 0; | |
lastRefresh = 0; | |
lastTrashRefresh = 0; | |
return; | |
} | |
}; | |
$rootScope.$watch( | |
function() {return Groups.byId}, | |
function() { | |
_.each(Groups.byId, function(group, groupId) { | |
if (angular.isUndefined(Contacts.byGroupId[groupId])) { | |
Contacts.byGroupId[groupId] = {} | |
} | |
}); | |
}); | |
// Keep the cached strings up to date | |
$rootScope.$watch( | |
function() {return Sorting.current}, | |
function() { | |
$log.log("Sorting changed, updating cached strings."); | |
applyFnToAllCachedContacts(updateCachedStrings); | |
} | |
); | |
return Contacts; | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment