Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
parent
93e3a48004
commit
b38dea0597
25901 changed files with 9982925 additions and 369 deletions
325
gaia/shared/js/fb/fb_reader_utils.js
Executable file
325
gaia/shared/js/fb/fb_reader_utils.js
Executable file
|
|
@ -0,0 +1,325 @@
|
|||
'use strict';
|
||||
|
||||
// Includes convenience functions for FB Contact Data
|
||||
// To use this library you need to include:
|
||||
// 'shared/js/fb/fb_request.js' and 'shared/js/fb/fb_data_reader.js'
|
||||
|
||||
var fb = self.fb || {};
|
||||
self.fb = fb;
|
||||
|
||||
if (!self.AuxFB) {
|
||||
self.AuxFb = (function() {
|
||||
var CATEGORY = 'facebook';
|
||||
var NOT_LINKED = 'not_linked';
|
||||
var LINKED = 'fb_linked';
|
||||
|
||||
// Shallow copy from source to target object
|
||||
function populate(source, target, propertyNames) {
|
||||
propertyNames.forEach(function(property) {
|
||||
var propertyValue = source[property];
|
||||
if (propertyValue) {
|
||||
if (Array.isArray(propertyValue)) {
|
||||
target[property] = propertyValue.slice(0, propertyValue.length);
|
||||
} else {
|
||||
target[property] = propertyValue;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Auxiliary function for merging
|
||||
function mergeFbData(dcontact, fbdata) {
|
||||
var multipleFields = ['email', 'tel', 'photo', 'org', 'adr'];
|
||||
|
||||
multipleFields.forEach(function(field) {
|
||||
if (!dcontact[field]) {
|
||||
dcontact[field] = [];
|
||||
}
|
||||
var items = fbdata[field];
|
||||
if (items) {
|
||||
items.forEach(function(item) {
|
||||
// If there are no duplicates the merge is done
|
||||
var dupList = checkDuplicates(field, item, dcontact[field],
|
||||
fbdata.shortTelephone);
|
||||
if (dupList.length === 0) {
|
||||
dcontact[field].push(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
var singleFields = ['bday', 'anniversary'];
|
||||
singleFields.forEach(function(field) {
|
||||
if (!dcontact[field]) {
|
||||
dcontact[field] = fbdata[field];
|
||||
}
|
||||
});
|
||||
|
||||
// To support the case in which the contact does not have a local name
|
||||
mergeNames(dcontact, fbdata);
|
||||
}
|
||||
|
||||
// Auxiliary function for merging names
|
||||
function mergeNames(devContact, fbContact) {
|
||||
var namesChanged = false;
|
||||
var nameFields = ['givenName', 'familyName'];
|
||||
nameFields.forEach(function(anameField) {
|
||||
// If the device contact does not have name fields setted
|
||||
// we use the Facebook ones
|
||||
var fieldValue = devContact[anameField];
|
||||
var fbValue = fbContact[anameField];
|
||||
if ((!Array.isArray(fieldValue) || fieldValue.length === 0) &&
|
||||
Array.isArray(fbValue) && fbValue.length > 0) {
|
||||
namesChanged = true;
|
||||
devContact[anameField] = (fieldValue && fieldValue[0]) || [];
|
||||
devContact[anameField].push(fbValue[0]);
|
||||
}
|
||||
});
|
||||
|
||||
if (namesChanged) {
|
||||
var givenName = devContact.givenName[0] || '';
|
||||
var familyName = devContact.familyName[0] || '';
|
||||
devContact.name = [givenName + ' ' + familyName];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns truthy if the device contact is a FB Friend
|
||||
*
|
||||
*/
|
||||
function isFbContact(devContact) {
|
||||
return (devContact && devContact.category &&
|
||||
devContact.category.indexOf(CATEGORY) !== -1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns truthy if the device contact is linked to a FB Friend
|
||||
*
|
||||
*/
|
||||
function isFbLinked(devContact) {
|
||||
return (devContact && devContact.category &&
|
||||
devContact.category.indexOf(LINKED) !== -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the data enriching the local contact with FB information
|
||||
*
|
||||
*/
|
||||
function getData(devContact) {
|
||||
var outReq = new fb.utils.Request();
|
||||
|
||||
window.setTimeout(function do_getData() {
|
||||
var uid = getFriendUid(devContact);
|
||||
|
||||
if (uid) {
|
||||
var fbreq = fb.contacts.get(uid);
|
||||
|
||||
fbreq.onsuccess = function() {
|
||||
var fbdata = fbreq.result;
|
||||
var out = mergeContact(devContact, fbdata);
|
||||
outReq.done(out);
|
||||
|
||||
};
|
||||
|
||||
fbreq.onerror = function() {
|
||||
outReq.failed(fbreq.error);
|
||||
};
|
||||
}
|
||||
else {
|
||||
outReq.done(devContact);
|
||||
}
|
||||
}, 0);
|
||||
|
||||
return outReq;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the FB Friend UID associated to a device contact
|
||||
*
|
||||
*/
|
||||
function getFriendUid(devContact) {
|
||||
var out = devContact.uid;
|
||||
|
||||
if (!out) {
|
||||
if (isFbLinked(devContact)) {
|
||||
out = getLinkedTo(devContact);
|
||||
}
|
||||
else if (devContact.category) {
|
||||
var idx = devContact.category.indexOf(CATEGORY);
|
||||
if (idx !== -1) {
|
||||
out = devContact.category[idx + 2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the UID of the FB Friend a device contact is linked to
|
||||
*
|
||||
*/
|
||||
function getLinkedTo(devContact) {
|
||||
var out;
|
||||
|
||||
if (devContact.category) {
|
||||
var idx = devContact.category.indexOf(LINKED);
|
||||
if (idx !== -1) {
|
||||
out = devContact.category[idx + 1];
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge a device contact with a FB Friend
|
||||
*
|
||||
*/
|
||||
function mergeContact(devContact, fbContact) {
|
||||
var out = devContact;
|
||||
|
||||
if (fbContact) {
|
||||
out = Object.create(null);
|
||||
out.updated = devContact.updated;
|
||||
out.published = devContact.published;
|
||||
|
||||
// The id comes from devContact and the rest of properties like
|
||||
// familyName, propertyName, etc... are defined in the proto object
|
||||
populate(devContact, out, Object.getOwnPropertyNames(devContact));
|
||||
populate(devContact, out,
|
||||
Object.getOwnPropertyNames(Object.getPrototypeOf(devContact)));
|
||||
|
||||
mergeFbData(out, fbContact);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a FB Contact (enriched with FB info) which has the tel number
|
||||
*
|
||||
*/
|
||||
function getContactByNumber(number, onsuccess, onerror) {
|
||||
var req = fb.contacts.getByPhone(number);
|
||||
|
||||
req.onsuccess = function get_by_phone_success(e) {
|
||||
var fbData = req.result;
|
||||
if (fbData) {
|
||||
fb.getMozContactByUid(fbData.uid, function merge(result) {
|
||||
if (Array.isArray(result) && result[0]) {
|
||||
var finalContact = fb.mergeContact(result[0], fbData);
|
||||
onsuccess(finalContact);
|
||||
}
|
||||
else {
|
||||
onsuccess(null);
|
||||
}
|
||||
}, function error_get_mozContact(err) {
|
||||
console.error('Error getting mozContact: ', err.name);
|
||||
onerror(err);
|
||||
});
|
||||
}
|
||||
else {
|
||||
onsuccess(null);
|
||||
}
|
||||
};
|
||||
|
||||
req.onerror = function() {
|
||||
onerror(req.error);
|
||||
};
|
||||
}
|
||||
|
||||
// Checks whether there is a duplicate for the field value
|
||||
// both in FB and in the local device Contact data
|
||||
// Returns an array with the values which are duplicated or empty if
|
||||
// no duplicates were found
|
||||
// Parameters are: field on which to search, the corresponding fbItem
|
||||
// the local device items, and extra FB Items which corresp to the short
|
||||
// telephone numbers allowing to filter out dups with intl-ed numbers
|
||||
function checkDuplicates(field, fbItem, devContactItems, extraFbItems) {
|
||||
var potentialDuplicatesFields = ['email', 'tel'];
|
||||
var out = [];
|
||||
|
||||
if (devContactItems &&
|
||||
potentialDuplicatesFields.indexOf(field) !== -1) {
|
||||
var total = devContactItems.length;
|
||||
for (var i = 0; i < total; i++) {
|
||||
var localValue = devContactItems[i].value;
|
||||
var fbValue = fbItem.value;
|
||||
// Checking for telephone international number matching
|
||||
if (localValue) {
|
||||
var trimedLocal = localValue.trim();
|
||||
if (trimedLocal === fbValue ||
|
||||
(field === 'tel' && Array.isArray(extraFbItems) &&
|
||||
extraFbItems.indexOf(trimedLocal) !== -1)) {
|
||||
out.push(trimedLocal);
|
||||
out.push(fbValue);
|
||||
}
|
||||
} // if(localValue)
|
||||
} // for
|
||||
} // if(devContactItems)
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mozContact associated to a certain FB UID
|
||||
*
|
||||
*/
|
||||
function getMozContactByUid(uid, onsuccess, onerror) {
|
||||
var filter = {
|
||||
filterBy: ['category'],
|
||||
filterValue: uid,
|
||||
filterOp: 'contains'
|
||||
};
|
||||
|
||||
var req = navigator.mozContacts.find(filter);
|
||||
req.onsuccess = function() {
|
||||
onsuccess(req.result);
|
||||
};
|
||||
req.onerror = function() {
|
||||
onerror(req.error);
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
'isFbContact': isFbContact,
|
||||
'isFbLinked': isFbLinked,
|
||||
'getData': getData,
|
||||
'getFriendUid': getFriendUid,
|
||||
'getLinkedTo': getLinkedTo,
|
||||
'mergeContact': mergeContact,
|
||||
'getContactByNumber': getContactByNumber,
|
||||
'getMozContactByUid': getMozContactByUid,
|
||||
'checkDuplicates': checkDuplicates,
|
||||
get CATEGORY() {
|
||||
return CATEGORY;
|
||||
},
|
||||
get LINKED() {
|
||||
return LINKED;
|
||||
},
|
||||
get NOT_LINKED() {
|
||||
return NOT_LINKED;
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
// This boilerplate code sets the AuxFb properties to the fb object
|
||||
var props = Object.keys(self.AuxFb);
|
||||
|
||||
for (var j = 0, end = props.length; j < end; j++) {
|
||||
/* jshint loopfunc: true */
|
||||
var prop = props[j];
|
||||
if (typeof self.fb[prop] === 'function') {
|
||||
self.fb[prop] = self.AuxFb[prop];
|
||||
}
|
||||
else {
|
||||
Object.defineProperty(self.fb, prop, {
|
||||
value: (function() {
|
||||
return self.AuxFb[prop];
|
||||
})(), writable: false, enumerable: true, configurable: false
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue