Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
191 lines
5.3 KiB
JavaScript
Executable file
191 lines
5.3 KiB
JavaScript
Executable file
/* global mozContact, oauthflow, ImportStatusData */
|
|
'use strict';
|
|
|
|
var utils = window.utils || {};
|
|
|
|
// Scale ratio for different devices
|
|
var SCALE_RATIO = window.devicePixelRatio || 1;
|
|
|
|
var LAST_IMPORT_TIMESTAMP_SUFFIX = '_last_import_timestamp';
|
|
|
|
function scale(size) {
|
|
return Math.round(SCALE_RATIO * size);
|
|
}
|
|
|
|
if (!utils.misc) {
|
|
utils.misc = {};
|
|
utils.misc.toMozContact = function(contact) {
|
|
var outContact = contact;
|
|
if (!(contact instanceof mozContact)) {
|
|
outContact = new mozContact(contact);
|
|
outContact.id = contact.id || outContact.id;
|
|
}
|
|
|
|
return outContact;
|
|
};
|
|
|
|
// This year indicates that the year can be ignored
|
|
const FLAG_YEAR_IGNORED = 9996;
|
|
utils.misc.FLAG_YEAR_IGNORED = FLAG_YEAR_IGNORED;
|
|
|
|
utils.misc.formatDate = function(date, customFormat) {
|
|
var dateString = null;
|
|
|
|
try {
|
|
var format = customFormat || {
|
|
month: 'short',
|
|
day: 'numeric'
|
|
};
|
|
|
|
var offset = date.getTimezoneOffset() * 60 * 1000;
|
|
var normalizedDate = new Date(date.getTime() + offset);
|
|
|
|
var year = normalizedDate.getFullYear();
|
|
if (year !== FLAG_YEAR_IGNORED) {
|
|
format.year = 'numeric';
|
|
}
|
|
var f = new Intl.DateTimeFormat(navigator.languages, format);
|
|
|
|
dateString = f.format(normalizedDate);
|
|
} catch (err) {
|
|
console.error('Error parsing date: ', err);
|
|
throw err;
|
|
}
|
|
|
|
return dateString;
|
|
};
|
|
|
|
// Parses a name to obtain a givenName and a familyName
|
|
// This is useful while importing contacts from SIM card
|
|
utils.misc.parseName = function(nameString) {
|
|
// Minimum length to consider a token as significative
|
|
var MIN_LENGHT_SIGNIFICATIVE = 3;
|
|
// Minimum length of a token to consider it a familyName
|
|
var MIN_LENGHT_FN = 2;
|
|
|
|
var out = {
|
|
givenName: '',
|
|
familyName: ''
|
|
};
|
|
|
|
if (!nameString) {
|
|
return out;
|
|
}
|
|
var str = nameString.trim();
|
|
if (!str) {
|
|
return out;
|
|
}
|
|
|
|
function startsWithUpper(str) {
|
|
var firstLetter = str.charAt(0);
|
|
var capFirstLetter = firstLetter.toLocaleUpperCase();
|
|
|
|
return (capFirstLetter === firstLetter);
|
|
}
|
|
|
|
// First step of the algorithm is to split the name in its tokens
|
|
var tokens = nameString.split(/\s+/);
|
|
var significativeTokens = {};
|
|
for (var j = 0; j < tokens.length; j++) {
|
|
var token = tokens[j];
|
|
// A significative token os one with that min length and which starts with
|
|
// uppercase letter
|
|
if (token.length > MIN_LENGHT_SIGNIFICATIVE || startsWithUpper(token)) {
|
|
significativeTokens[token] = true;
|
|
}
|
|
}
|
|
|
|
var totalTokens = tokens.length;
|
|
var lastToken = totalTokens - 1;
|
|
var rolePrevToken;
|
|
var remainingTokens = Object.keys(significativeTokens).length;
|
|
var outGivenNames = [], outFamilyNames = [];
|
|
// We need to keep the totals in a different variable as a familyName
|
|
// can be composed by more than one token
|
|
var numFns = 0;
|
|
|
|
while (lastToken >= 0) {
|
|
if (significativeTokens[tokens[lastToken]]) {
|
|
remainingTokens--;
|
|
}
|
|
|
|
var currToken = tokens[lastToken],
|
|
nextToken = tokens[lastToken + 1],
|
|
prevToken = tokens[lastToken - 1];
|
|
|
|
// The last element is taken as part of the family name
|
|
if (!nextToken && prevToken) {
|
|
outFamilyNames.push(currToken);
|
|
numFns++;
|
|
rolePrevToken = 'FN';
|
|
}
|
|
else if (!prevToken) {
|
|
outGivenNames.push(currToken);
|
|
rolePrevToken = 'GN';
|
|
}
|
|
else if (nextToken) {
|
|
if (!significativeTokens[currToken]) {
|
|
if (rolePrevToken === 'FN') {
|
|
// Here the number of fns is not incremented as this is a non
|
|
// significative token
|
|
outFamilyNames.push(currToken);
|
|
}
|
|
else {
|
|
outGivenNames.push(currToken);
|
|
}
|
|
}
|
|
else if (currToken.length < MIN_LENGHT_FN) {
|
|
outGivenNames.push(currToken);
|
|
rolePrevToken = 'GN';
|
|
}
|
|
else {
|
|
// Number of familyNames will be two at most
|
|
// Preference is given to the givenName over familyName
|
|
// We prefer two givenNames instead of two family Names
|
|
if (remainingTokens >= 2 && numFns < 2) {
|
|
outFamilyNames.push(currToken);
|
|
numFns++;
|
|
rolePrevToken = 'FN';
|
|
}
|
|
else {
|
|
outGivenNames.push(currToken);
|
|
rolePrevToken = 'GN';
|
|
}
|
|
}
|
|
}
|
|
|
|
lastToken--;
|
|
}
|
|
|
|
out.givenName = outGivenNames.reverse().join(' ').trim();
|
|
out.familyName = outFamilyNames.reverse().join(' ').trim();
|
|
|
|
return out;
|
|
};
|
|
|
|
utils.misc.getPreferredPictureBox = function() {
|
|
var imgThumbSize = oauthflow.params.facebook.imgThumbSize;
|
|
var out = {
|
|
width: scale(imgThumbSize)
|
|
};
|
|
|
|
out.height = out.width;
|
|
|
|
return out;
|
|
};
|
|
|
|
utils.misc.getPreferredPictureDetail = function() {
|
|
var imgDetailWidth = oauthflow.params.facebook.imgDetailWidth;
|
|
return scale(imgDetailWidth);
|
|
};
|
|
|
|
utils.misc.setTimestamp = function(type, callback) {
|
|
ImportStatusData.put(type + LAST_IMPORT_TIMESTAMP_SUFFIX, Date.now())
|
|
.then(callback);
|
|
};
|
|
|
|
utils.misc.getTimestamp = function(type, callback) {
|
|
ImportStatusData.get(type + LAST_IMPORT_TIMESTAMP_SUFFIX)
|
|
.then(callback);
|
|
};
|
|
}
|