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:
OverSu 2026-09-30 23:13:03 +02:00
commit b38dea0597
25901 changed files with 9982925 additions and 369 deletions

View file

@ -0,0 +1,191 @@
/* 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);
};
}