Skip to content

Commit

Permalink
Bug 1115329 - [Contacts]Device fails to import contacts and go back t…
Browse files Browse the repository at this point in the history
…o Home automatically, when you import a large number of contacts from memory card. r=francisco
  • Loading branch information
ferjm committed Oct 1, 2015
1 parent d1f42d3 commit 569a079
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 78 deletions.
121 changes: 68 additions & 53 deletions apps/communications/contacts/js/views/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,10 @@ contacts.Settings = (function() {
var cancelled = false;
var importer = null;
var progress = Contacts.showOverlay(
'memoryCardContacts-reading', 'activityBar');
'memoryCardContacts-importing',
'activityBar',
'infiniteProgress'
);
utils.overlay.showMenu();
utils.overlay.oncancel = function() {
cancelled = true;
Expand All @@ -590,69 +593,81 @@ contacts.Settings = (function() {
}

if (fileArray.length) {
utils.sdcard.getTextFromFiles(fileArray, '', onFiles);
var promises = [];
fileArray.forEach(file => {
promises.push(utils.sdcard.getTextFromFile(file, onContacts));
});
Promise.all(promises).then(results => {
var numDupsMerged = results.reduce((sum, current) => {
return sum + current;
});
window.setTimeout(() => {
utils.misc.setTimestamp('sd', () => {
// Once the timestamp is saved, update the list
updateTimestamps();
checkNoContacts();
resetWait(wakeLock);

if (!cancelled) {
var msg1 = {
id: 'memoryCardContacts-imported3',
args: {
n: importedContacts
}
};
var msg2 = !numDupsMerged ? null : {
id: 'contactsMerged',
args: {
numDups: numDupsMerged
}
};

utils.status.show(msg1, msg2);

if (typeof cb === 'function') {
cb();
}
}
});
}, DELAY_FEEDBACK);
}).catch(error => {
import_error(error);
});
} else {
import_error('No contacts were found.', cb);
}
});

function onFiles(err, text) {
if (err) {
return import_error(err, cb);
}

function onContacts(text) {
if (cancelled) {
return;
return Promise.reject();
}
return new Promise((resolve, reject) => {
importer = new VCFReader(text);
if (!text || !importer) {
var error = 'No contacts were found';
import_error(error);
reject(error);
return;
}

importer = new VCFReader(text);
if (!text || !importer) {
return import_error('No contacts were found.', cb);
}

importer.onread = import_read;
importer.onimported = imported_contact;
importer.onerror = import_error;

importer.process(function import_finish(total, numDupsMerged) {
window.setTimeout(function onfinish_import() {
utils.misc.setTimestamp('sd', function() {
// Once the timestamp is saved, update the list
updateTimestamps();
checkNoContacts();
resetWait(wakeLock);

if (!cancelled) {
var msg1 = {
id: 'memoryCardContacts-imported3',
args: {
n: importedContacts
}
};
var msg2 = !numDupsMerged ? null : {
id: 'contactsMerged',
args: {
numDups: numDupsMerged
}
};

utils.status.show(msg1, msg2);

if (typeof cb === 'function') {
cb();
}
}
});
}, DELAY_FEEDBACK);
importer.onimported = imported_contact;
importer.onerror = error => {
import_error(error);
reject(error);
};

importer.process((unused, numDupsMerged) => {
if (cancelled) {
reject('Cancelled');
Contacts.hideOverlay();
return;
}
resolve(numDupsMerged);
});
});
}

function import_read(n) {
progress.setClass('progressBar');
progress.setHeaderMsg('memoryCardContacts-importing');
progress.setTotal(n);
}

function imported_contact() {
importedContacts++;
progress.update();
Expand Down
6 changes: 5 additions & 1 deletion apps/communications/contacts/test/unit/mock_sdcard.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
'use strict';

/* global MockVCFReader */

/* exported MockSdCard */

var MockSdCard = function MockSdCard() {
Expand Down Expand Up @@ -110,8 +113,9 @@ var MockSdCard = function MockSdCard() {
}
]);
},
'getTextFromFiles': function getTextFromFiles(fileArray, contents, cb) {
'getTextFromFile': function getTextFromFile(fileArray, cb) {
cb(null, mock_sdcard_vcf);
return Promise.resolve(MockVCFReader.prototype.numDuplicated);
},
'subscribeToChanges': subscribeToChanges,
'unsubscribeToChanges': unsubscribeToChanges
Expand Down
6 changes: 4 additions & 2 deletions shared/js/contacts/import/utilities/overlay.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@ var utils = window.utils || {};
progressElement.setAttribute('value', 0);

function showMessage() {
var attributes = progressTextId == 'infiniteProgress' ?
{ n: counter } :
{ current: counter, total: total };
navigator.mozL10n.setAttributes(progressMsg,
progressTextId,
{ current: counter, total: total }
);
attributes);
}

/**
Expand Down
58 changes: 38 additions & 20 deletions shared/js/contacts/import/utilities/sdcard.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,31 +139,49 @@ if (!utils.sdcard) {
};

/**
* Extracts and concatenates text from the given array of file objects.
* Incrementally extracts vcard text from a file.
*
* @param {Array} fileArray Array of File Objects.
* @param {String} contents Accumulated text from the previous recursive call.
* @param {Function} cb Function to call when the work is finished.
* @param {Object} file File Object.
* @param {Function} cb Function to call for each chunk of vcards retrieved
* from the file.
*/
SdCard.getTextFromFiles = function(fileArray, contents, cb) {
contents = contents || '';
if (!fileArray || !fileArray.length) {
return cb && cb(null, contents);
SdCard.getTextFromFile = function(file, cb) {
if (!file) {
return Promise.reject();
}
return new Promise((resolve, reject) => {
const END_VCARD = 'end:vcard';
const CHUNK_SIZE = 1 * 1024 * 1024; // 1Mb

var reader = new FileReader();
reader.onload = function onloaded() {
contents += reader.result + '\n';
SdCard.getTextFromFiles(fileArray, contents, cb);
};
var fileReader = new FileReader();

try {
reader.readAsText(fileArray.shift());
}
catch (ex) {
window.console.error('Problem reading file: ', ex.stack);
SdCard.getTextFromFiles(fileArray, contents, cb);
}
var result = 0;

(function readChunk(offset, buffer) {
if (offset >= file.size) {
resolve(result);
return;
}
var chunk = file.slice(offset, offset + CHUNK_SIZE);
offset += CHUNK_SIZE;
fileReader.readAsText(chunk);
fileReader.onload = function() {
buffer += fileReader.result;
if (!buffer.match(/end:vcard/gi)) {
readChunk(offset, buffer);
return;
}
var lastContactInChunk =
buffer.toLowerCase().lastIndexOf(END_VCARD) + END_VCARD.length;
cb(buffer.substr(0, lastContactInChunk)).then(partialResult => {
result += partialResult;
readChunk(offset, buffer.substr(lastContactInChunk + 1));
}).catch(error => {
console.warn(error);
});
};
})(0 /* initial offset */, '' /* initial empty buffer */);
});
};

// Subscribe a callback for sdcard changes. A name is needed
Expand Down
10 changes: 8 additions & 2 deletions shared/locales/import_contacts/import_contacts.en-US.properties
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ simContacts-imported3[other] = Imported {{n}} contacts
# SD Card import
memoryCardContacts-import = Import contacts from memory card
memoryCardContacts-importing = Importing contacts from memory card…
memoryCardContacts-reading = Reading from memory card…
memoryCardContacts-error = Could not import contacts from memory card
memoryCardContacts-imported3 = {[ plural(n) ]}
memoryCardContacts-imported3[zero] = No contacts detected on memory card to import
Expand All @@ -30,7 +29,14 @@ memoryCardContacts-imported3[few] = Imported {{n}} contacts
memoryCardContacts-imported3[many] = Imported {{n}} contacts
memoryCardContacts-imported3[other] = Imported {{n}} contacts

genericProgress = {{current}}/{{total}}
genericProgress = {{current}}/{{total}}
infiniteProgress = {[ plural(n) ]}
infiniteProgress[zero] = No contacts imported yet
infiniteProgress[one] = Imported one contact
infiniteProgress[two] = Imported {{n}} contacts
infiniteProgress[few] = Imported {{n}} contacts
infiniteProgress[many] = Imported {{n}} contacts
infiniteProgress[other] = Imported {{n}} contacts

# Status
friendsUpdated = {[ plural(numFriends) ]}
Expand Down

0 comments on commit 569a079

Please sign in to comment.