[WO-382] Lazy loading for attachments

This commit is contained in:
Felix Hammerl 2014-05-12 22:07:25 +02:00
parent c4d0029f34
commit 1795f2af45
4 changed files with 96 additions and 5 deletions

View File

@ -117,7 +117,7 @@ define(function(require) {
var email = $scope.state.mailList.selected;
emailDao.getAttachment({
path: folder.path,
folder: folder.path,
uid: email.uid,
attachment: attachment
}, function(err) {

View File

@ -306,9 +306,19 @@ define(function(require) {
var localMessage = localMessages[0];
// treat attachment and non-attachment body parts separately:
// we need to fetch the content for non-attachment body parts (encrypted, signed, text, html)
// but we spare the effort and fetch attachment content later upon explicit user request.
var contentParts = localMessage.bodyParts.filter(function(bodyPart) {
return bodyPart.type !== "attachment";
});
var attachmentParts = localMessage.bodyParts.filter(function(bodyPart) {
return bodyPart.type === "attachment";
});
// do we need to fetch content from the imap server?
var needsFetch = false;
localMessage.bodyParts.forEach(function(part) {
contentParts.forEach(function(part) {
needsFetch = (typeof part.content === 'undefined');
});
@ -324,15 +334,16 @@ define(function(require) {
self._emailSync._getBodyParts({
folder: folder,
uid: localMessage.uid,
bodyParts: localMessage.bodyParts
bodyParts: contentParts
}, function(err, parsedBodyParts) {
if (err) {
done(err);
return;
}
message.bodyParts = parsedBodyParts;
localMessage.bodyParts = parsedBodyParts;
// piece together the parsed bodyparts and the empty attachments which have not been parsed
message.bodyParts = parsedBodyParts.concat(attachmentParts);
localMessage.bodyParts = parsedBodyParts.concat(attachmentParts);
// persist it to disk
self._emailSync._localStoreMessages({
@ -384,6 +395,22 @@ define(function(require) {
}
};
EmailDAO.prototype.getAttachment = function(options, callback) {
this._emailSync._getBodyParts({
folder: options.folder,
uid: options.uid,
bodyParts: [options.attachment]
}, function(err, parsedBodyParts) {
if (err) {
callback(err);
return;
}
options.attachment.content = parsedBodyParts[0].content;
callback(err, err ? undefined : options.attachment);
});
};
EmailDAO.prototype.decryptBody = function(options, callback) {
var self = this,
message = options.message;

View File

@ -447,6 +447,13 @@ define(function(require) {
return;
}
// this enables us to already show the attachment clip in the message list ui
messages.forEach(function(message) {
message.attachments = message.bodyParts.filter(function(bodyPart) {
return bodyPart.type === 'attachment';
});
});
// if persisting worked, add them to the messages array
folder.messages = folder.messages.concat(messages);
self.onIncomingMessage(messages);

View File

@ -866,6 +866,63 @@ define(function(require) {
});
});
describe('getAttachment', function() {
var folder = 'asdasdasdasdasd',
uid = 1234,
imapGetStub;
beforeEach(function() {
imapGetStub = sinon.stub(emailSync, '_getBodyParts');
});
afterEach(function() {
emailSync._getBodyParts.restore();
});
it('should fetch an attachment from imap', function(done) {
var attmt = {};
imapGetStub.withArgs({
folder: folder,
uid: uid,
bodyParts: [attmt]
}).yieldsAsync(null, [{
content: 'CONTENT!!!'
}]);
dao.getAttachment({
folder: folder,
uid: uid,
attachment: attmt
}, function(err, fetchedAttmt) {
expect(err).to.not.exist;
expect(fetchedAttmt).to.equal(attmt);
expect(attmt.content).to.not.be.empty;
expect(imapGetStub.calledOnce).to.be.true;
done();
});
});
it('should error during fetch', function(done) {
var attmt = {};
imapGetStub.yieldsAsync({});
dao.getAttachment({
folder: folder,
uid: uid,
attachment: attmt
}, function(err, fetchedAttmt) {
expect(err).to.exist;
expect(fetchedAttmt).to.not.exist;
expect(imapGetStub.calledOnce).to.be.true;
done();
});
});
});
describe('decryptBody', function() {
it('should do nothing when the message is not encrypted', function() {
var message = {