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
46
gaia/apps/communications/contacts/views/vcard_load/js/boot.js
Executable file
46
gaia/apps/communications/contacts/views/vcard_load/js/boot.js
Executable file
|
|
@ -0,0 +1,46 @@
|
|||
/* global LazyLoader, VCardLoadUI, VCardLoadController, VCardHandler */
|
||||
'use strict';
|
||||
|
||||
/*
|
||||
* This class is the one in charge of loading the minimum set of
|
||||
* resources needed for the view to load. Any other JS/CSS/Element
|
||||
* not needed in the critical path *must* be lazy loaded when needed.
|
||||
*
|
||||
* Once localization and all the basic JS/CSS/Elements are loaded,
|
||||
* we will initialize UI and Controller. Both JS classes *must* be
|
||||
* independent and will communicate through events.
|
||||
*/
|
||||
|
||||
window.addEventListener('DOMContentLoaded', function() {
|
||||
LazyLoader.load(['/shared/js/l10n.js']).then(function() {
|
||||
LazyLoader.load([
|
||||
document.getElementById('multiple-select-view')
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
window.addEventListener('load', function() {
|
||||
var dependencies = [
|
||||
'/shared/js/contacts/import/utilities/vcard_reader.js',
|
||||
'/contacts/views/vcard_load/js/vcard_handler.js',
|
||||
'/contacts/views/vcard_load/js/vcard_load_ui.js',
|
||||
'/contacts/views/vcard_load/js/vcard_load_controller.js'
|
||||
];
|
||||
|
||||
LazyLoader.load(dependencies).then(function() {
|
||||
VCardLoadUI.init();
|
||||
VCardLoadController.init();
|
||||
|
||||
navigator.mozSetMessageHandler('activity', function(activity) {
|
||||
VCardLoadController.setActivity(activity);
|
||||
VCardHandler.handle(activity)
|
||||
.then(contacts => {
|
||||
var data = activity.source.data;
|
||||
var filename = VCardHandler.getFileName(data.filename || data.src);
|
||||
// Do Render
|
||||
VCardLoadUI.render(contacts, filename);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
58
gaia/apps/communications/contacts/views/vcard_load/js/vcard_handler.js
Executable file
58
gaia/apps/communications/contacts/views/vcard_load/js/vcard_handler.js
Executable file
|
|
@ -0,0 +1,58 @@
|
|||
/* global VCardReader */
|
||||
|
||||
(function(exports) {
|
||||
'use strict';
|
||||
|
||||
function handle(activity) {
|
||||
return getvCardReader(activity.source.data.blob).then(readvCard);
|
||||
}
|
||||
|
||||
function getvCardReader(blob) {
|
||||
return new Promise((resolve, reject) => {
|
||||
var fileReader = new FileReader();
|
||||
fileReader.readAsText(blob);
|
||||
fileReader.onloadend = function() {
|
||||
resolve(new VCardReader(fileReader.result));
|
||||
};
|
||||
fileReader.onerror = function() {
|
||||
console.error('The blob could not be read as a file.');
|
||||
reject(fileReader.error);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function readvCard(vCardReader) {
|
||||
var contacts = [];
|
||||
return new Promise(function(resolve, reject) {
|
||||
var cursor = vCardReader.getAll();
|
||||
cursor.onsuccess = function(event) {
|
||||
if (!event.target.result) {
|
||||
resolve(contacts);
|
||||
return;
|
||||
}
|
||||
|
||||
contacts.push(event.target.result);
|
||||
cursor.continue();
|
||||
};
|
||||
|
||||
cursor.onerror = function(event) {
|
||||
console.error('Error while retrieving cursor from vcard');
|
||||
reject();
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function getFileName(path) {
|
||||
var barIndex = path.lastIndexOf('/');
|
||||
if (barIndex > -1) {
|
||||
path = path.substring(barIndex + 1);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
exports.VCardHandler = {
|
||||
'handle': handle,
|
||||
'getFileName': getFileName
|
||||
};
|
||||
|
||||
})(window);
|
||||
100
gaia/apps/communications/contacts/views/vcard_load/js/vcard_load_controller.js
Executable file
100
gaia/apps/communications/contacts/views/vcard_load/js/vcard_load_controller.js
Executable file
|
|
@ -0,0 +1,100 @@
|
|||
/* global LazyLoader, ContactsService, Matcher, contacts */
|
||||
|
||||
(function(exports) {
|
||||
'use strict';
|
||||
var _activity;
|
||||
const STATUS_TIMEOUT = 3000; // ms before closing view which shows status msg
|
||||
|
||||
function close() {
|
||||
if (_activity) {
|
||||
_activity.postResult({});
|
||||
} else {
|
||||
window.history.back();
|
||||
}
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
window.removeEventListener('closeAction', close);
|
||||
window.removeEventListener('saveAction', importAll);
|
||||
}
|
||||
|
||||
function importAll(evt) {
|
||||
if (!evt.detail.contactsToImport) {
|
||||
console.error('Missing parameter');
|
||||
return;
|
||||
}
|
||||
|
||||
cleanup();
|
||||
|
||||
var contactsToImport = evt.detail.contactsToImport;
|
||||
|
||||
var numDupsMerged = 0,
|
||||
importedContacts = 0,
|
||||
parsedContacts = 0;
|
||||
const DEPENDENCIES = [
|
||||
'/shared/js/contacts/import/utilities/status.js',
|
||||
'/shared/js/simple_phone_matcher.js',
|
||||
'/shared/js/contacts/contacts_matcher.js',
|
||||
'/shared/js/contacts/contacts_merger.js',
|
||||
'/shared/js/contacts/merger_adapter.js',
|
||||
'/contacts/services/contacts.js',
|
||||
'/shared/js/text_normalizer.js'
|
||||
];
|
||||
LazyLoader.load(DEPENDENCIES, function() {
|
||||
contactsToImport.forEach((contact, index) => {
|
||||
Matcher.match(contact, 'passive', {
|
||||
onmatch: (matches) => {
|
||||
var callbacks = {
|
||||
success: () => {
|
||||
numDupsMerged++;
|
||||
doContinue(true);
|
||||
},
|
||||
error: doContinue
|
||||
};
|
||||
contacts.adaptAndMerge(contact, matches, callbacks);
|
||||
},
|
||||
onmismatch: () => {
|
||||
ContactsService.save(
|
||||
contact,
|
||||
function(e) {
|
||||
if (e) {
|
||||
console.error(e);
|
||||
doContinue();
|
||||
return;
|
||||
}
|
||||
doContinue(true);
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function doContinue(isContactImported) {
|
||||
parsedContacts++;
|
||||
if (isContactImported) {
|
||||
importedContacts++;
|
||||
}
|
||||
|
||||
if (contactsToImport.length <= parsedContacts) {
|
||||
window.dispatchEvent(new CustomEvent('showStatusAction', {
|
||||
'detail': {
|
||||
'numDups': numDupsMerged,
|
||||
'importedContacts': importedContacts
|
||||
}
|
||||
}));
|
||||
window.setTimeout(close, STATUS_TIMEOUT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exports.VCardLoadController = {
|
||||
init: function() {
|
||||
window.addEventListener('closeAction', close);
|
||||
window.addEventListener('saveAction', importAll);
|
||||
},
|
||||
setActivity: function(activity) {
|
||||
_activity = activity;
|
||||
}
|
||||
};
|
||||
})(window);
|
||||
97
gaia/apps/communications/contacts/views/vcard_load/js/vcard_load_ui.js
Executable file
97
gaia/apps/communications/contacts/views/vcard_load/js/vcard_load_ui.js
Executable file
|
|
@ -0,0 +1,97 @@
|
|||
/*global utils */
|
||||
|
||||
(function(exports) {
|
||||
'use strict';
|
||||
|
||||
var contactsToImport = [];
|
||||
var header, saveButton, container, template, title;
|
||||
|
||||
function cacheElements() {
|
||||
header = document.getElementById('multiple-select-view-header');
|
||||
saveButton = document.getElementById('save-button');
|
||||
container = document.getElementById('multiple-select-container');
|
||||
template = document.getElementById('contactToImportTemplate');
|
||||
title = document.getElementById('multiple-select-view-title');
|
||||
}
|
||||
|
||||
function addListeners() {
|
||||
saveButton.addEventListener('click',
|
||||
dispatchEvent.bind(null, 'saveAction',
|
||||
{'contactsToImport': contactsToImport}));
|
||||
header.addEventListener('action', dispatchEvent.bind(null, 'closeAction'));
|
||||
window.addEventListener('showStatusAction', onShowStatus);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes references to DOM elements. This is needed before calling
|
||||
* render.
|
||||
*/
|
||||
function init() {
|
||||
cacheElements();
|
||||
addListeners();
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to preview which contacts will be imported. Requires to call init
|
||||
* first when DOM is ready.
|
||||
*
|
||||
* @param cursor - Reader object to continue reading from vCard.
|
||||
* @param {string} filename - Name of the vcf file we are reading from.
|
||||
*/
|
||||
function render(contacts, filename) {
|
||||
container.innerHTML = ''; // Avoids rendering the same content twice.
|
||||
title.textContent = filename;
|
||||
|
||||
contacts.forEach(doRenderContact);
|
||||
|
||||
function doRenderContact(contact) {
|
||||
var clone = document.importNode(template.content, true);
|
||||
|
||||
var contactData = clone.querySelectorAll('p');
|
||||
contactData[0].textContent =
|
||||
Array.isArray(contact.name) && contact.name[0];
|
||||
var org = (Array.isArray(contact.org) && contact.org[0]) ?
|
||||
contact.org[0] : '';
|
||||
contactData[1].textContent = org;
|
||||
|
||||
if (Array.isArray(contact.photo) && contact.photo[0] instanceof Blob) {
|
||||
var picture = clone.querySelector('aside span');
|
||||
picture.style.backgroundImage = 'url(' +
|
||||
window.URL.createObjectURL(contact.photo[0]) + ')';
|
||||
}
|
||||
|
||||
contactsToImport.push(contact);
|
||||
container.appendChild(clone);
|
||||
}
|
||||
}
|
||||
|
||||
function dispatchEvent(name, data) {
|
||||
window.dispatchEvent(new CustomEvent(name, {'detail': data}));
|
||||
}
|
||||
|
||||
function onShowStatus(evt) {
|
||||
if (!evt.detail) {
|
||||
return;
|
||||
}
|
||||
|
||||
var imported = evt.detail.importedContacts,
|
||||
merged = evt.detail.numDups;
|
||||
|
||||
utils.status.show({
|
||||
id: 'vCardContacts-imported',
|
||||
args: {
|
||||
n: imported
|
||||
}
|
||||
}, {
|
||||
id: 'contactsMerged',
|
||||
args: {
|
||||
numDups: merged
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
exports.VCardLoadUI = {
|
||||
'init': init,
|
||||
'render': render
|
||||
};
|
||||
})(window);
|
||||
4
gaia/apps/communications/contacts/views/vcard_load/style/vcard_load.css
Executable file
4
gaia/apps/communications/contacts/views/vcard_load/style/vcard_load.css
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
aside span {
|
||||
background-position: center;
|
||||
background-size: 5rem;
|
||||
}
|
||||
64
gaia/apps/communications/contacts/views/vcard_load/vcard_load.html
Executable file
64
gaia/apps/communications/contacts/views/vcard_load/vcard_load.html
Executable file
|
|
@ -0,0 +1,64 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
|
||||
<meta charset="utf-8">
|
||||
<meta name="theme-group" content="theme-communications">
|
||||
<meta name="theme-color" content="var(--header-background)">
|
||||
<title> Contacts </title>
|
||||
|
||||
<!-- Building Blocks -->
|
||||
<link href="/shared/style/input_areas.css" rel="stylesheet">
|
||||
<link href="/shared/style/lists.css" rel="stylesheet">
|
||||
<link href="/shared/style/scrolling.css" rel="stylesheet">
|
||||
<link href="/shared/style/buttons.css" rel="stylesheet">
|
||||
<link href="/shared/style/progress_activity.css" rel="stylesheet">
|
||||
<link href="/shared/style/status.css" rel="stylesheet">
|
||||
<link href="/shared/style/switches.css" rel="stylesheet">
|
||||
<link href="/shared/style/confirm.css" rel="stylesheet">
|
||||
<link href="/shared/style/action_menu.css" rel="stylesheet">
|
||||
<link href="/shared/style/edit_mode.css" rel="stylesheet">
|
||||
<link href="/shared/style/animations.css" rel="stylesheet">
|
||||
|
||||
<link href="/contacts/style/app.css" rel="stylesheet">
|
||||
<link href="/contacts/style/contacts.css" rel="stylesheet">
|
||||
<link href="/contacts/style/overlay.css" rel="stylesheet">
|
||||
<link href="/shared/pages/import/style/curtain_frame.css" rel="stylesheet">
|
||||
<link href="/contacts/style/status.css" rel="stylesheet">
|
||||
<link href="/shared/style/contacts.css" rel="stylesheet">
|
||||
<link href="/shared/style/contacts/contacts_buttons.css" rel="stylesheet">
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="app://theme.gaiamobile.org/shared/elements/gaia-theme/gaia-theme.css" />
|
||||
|
||||
<!-- Web Components -->
|
||||
<script defer src="/shared/elements/config.js"></script>
|
||||
<script defer src="/shared/js/component_utils.js"></script>
|
||||
<script defer src="/shared/elements/gaia_subheader/script.js"></script>
|
||||
<script defer src="/shared/elements/gaia-header/dist/gaia-header.js"></script>
|
||||
|
||||
|
||||
<!-- Localization -->
|
||||
<link rel="localization" href="/shared/elements/gaia_menu/locales/gaia_menu.{locale}.properties">
|
||||
|
||||
<script defer src="/shared/js/html_imports.js"></script>
|
||||
<script defer src="/shared/js/lazy_loader.js"></script>
|
||||
<script defer src='/contacts/views/vcard_load/js/boot.js'></script>
|
||||
|
||||
<meta name="defaultLanguage" content="en-US">
|
||||
<meta name="availableLanguages" content="en-US">
|
||||
<link rel="localization" href="/contacts/locales/contacts.{locale}.properties">
|
||||
<link rel="localization" href="/shared/locales/import_contacts/import_contacts.{locale}.properties">
|
||||
<link rel="localization" href="/shared/locales/date/date.{locale}.properties">
|
||||
<link rel="localization" href="/shared/locales/phone_types/phone_types.{locale}.properties">
|
||||
|
||||
<!-- Load just the templates needed -->
|
||||
<link rel="import" href="/contacts/elements/multiple_select.html">
|
||||
<link rel="import" href="/contacts/elements/status.html">
|
||||
|
||||
</head>
|
||||
|
||||
<body role="application" class="app-contacts skin-comms theme-communications">
|
||||
<section is="multiple-select-view" id="multiple-select-view" role="region" class="view current"></section>
|
||||
<section is="status-message" id="statusMsg" role="status" class="hidden"></section>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Reference in a new issue