diff --git a/src/js/controller/app/account.js b/src/js/controller/app/account.js index 0ad4204..86df281 100644 --- a/src/js/controller/app/account.js +++ b/src/js/controller/app/account.js @@ -1,6 +1,6 @@ 'use strict'; -var AccountCtrl = function($scope, auth, keychain, pgp, appConfig, download, dialog) { +var AccountCtrl = function($scope, $q, auth, keychain, pgp, appConfig, download, dialog) { var userId = auth.emailAddress; if (!userId) { return; @@ -34,12 +34,13 @@ var AccountCtrl = function($scope, auth, keychain, pgp, appConfig, download, dia // $scope.exportKeyFile = function() { - keychain.getUserKeyPair(userId, function(err, keys) { - if (err) { - dialog.error(err); - return; - } + return $q(function(resolve) { + resolve(); + }).then(function() { + return keychain.getUserKeyPair(userId); + + }).then(function(keys) { var keyId = keys.publicKey._id; var file = 'whiteout_mail_' + userId + '_' + keyId.substring(8, keyId.length); @@ -48,7 +49,8 @@ var AccountCtrl = function($scope, auth, keychain, pgp, appConfig, download, dia filename: file + '.asc', contentType: 'text/plain' }); - }); + + }).catch(dialog.error); }; }; diff --git a/src/js/controller/app/action-bar.js b/src/js/controller/app/action-bar.js index e718a49..0c228f8 100644 --- a/src/js/controller/app/action-bar.js +++ b/src/js/controller/app/action-bar.js @@ -2,7 +2,7 @@ var JUNK_FOLDER_TYPE = 'Junk'; -var ActionBarCtrl = function($scope, email, dialog, status) { +var ActionBarCtrl = function($scope, $q, email, dialog, status) { // // scope functions @@ -23,24 +23,28 @@ var ActionBarCtrl = function($scope, email, dialog, status) { // show message status.update('Moving message...'); - email.moveMessage({ - folder: currentFolder(), - destination: destination, - message: message - }, function(err) { - if (err) { - // show errors where appropriate - if (err.code === 42) { - $scope.select(message); - status.update('Unable to move message in offline mode!'); - return; - } - status.update('Error during move!'); - dialog.error(err); + return $q(function(resolve) { + resolve(); + + }).then(function() { + return email.moveMessage({ + folder: currentFolder(), + destination: destination, + message: message + }); + + }).then(function() { + status.update('Online'); + + }).catch(function(err) { + // show errors where appropriate + if (err.code === 42) { + $scope.select(message); + status.update('Unable to move message in offline mode!'); return; } - status.update('Message moved.'); - $scope.$apply(); + status.update('Error during move!'); + return dialog.error(err); }); }; @@ -83,23 +87,27 @@ var ActionBarCtrl = function($scope, email, dialog, status) { status.setReading(false); status.update('Deleting message...'); - email.deleteMessage({ - folder: currentFolder(), - message: message - }, function(err) { - if (err) { - // show errors where appropriate - if (err.code === 42) { - $scope.select(message); - status.update('Unable to delete message in offline mode!'); - return; - } - status.update('Error during delete!'); - dialog.error(err); + return $q(function(resolve) { + resolve(); + + }).then(function() { + return email.deleteMessage({ + folder: currentFolder(), + message: message + }); + + }).then(function() { + status.update('Online'); + + }).catch(function(err) { + // show errors where appropriate + if (err.code === 42) { + $scope.select(message); + status.update('Unable to delete message in offline mode!'); return; } - status.update('Message deleted.'); - $scope.$apply(); + status.update('Error during delete!'); + return dialog.error(err); }); }; @@ -130,25 +138,29 @@ var ActionBarCtrl = function($scope, email, dialog, status) { var originalState = message.unread; message.unread = unread; - email.setFlags({ - folder: currentFolder(), - message: message - }, function(err) { - if (err && err.code === 42) { + + return $q(function(resolve) { + resolve(); + + }).then(function() { + return email.setFlags({ + folder: currentFolder(), + message: message + }); + + }).then(function() { + status.update('Online'); + + }).catch(function(err) { + if (err.code === 42) { // offline, restore message.unread = originalState; status.update('Unable to mark message in offline mode!'); return; } - if (err) { - status.update('Error on sync!'); - dialog.error(err); - return; - } - - status.update('Online'); - $scope.$apply(); + status.update('Error on sync!'); + return dialog.error(err); }); }; @@ -176,25 +188,29 @@ var ActionBarCtrl = function($scope, email, dialog, status) { var originalState = message.flagged; message.flagged = flagged; - email.setFlags({ - folder: currentFolder(), - message: message - }, function(err) { - if (err && err.code === 42) { + + return $q(function(resolve) { + resolve(); + + }).then(function() { + return email.setFlags({ + folder: currentFolder(), + message: message + }); + + }).then(function() { + status.update('Online'); + + }).catch(function(err) { + if (err.code === 42) { // offline, restore message.unread = originalState; status.update('Unable to ' + (flagged ? 'add star to' : 'remove star from') + ' message in offline mode!'); return; } - if (err) { - status.update('Error on sync!'); - dialog.error(err); - return; - } - - status.update('Online'); - $scope.$apply(); + status.update('Error on sync!'); + return dialog.error(err); }); }; @@ -208,12 +224,27 @@ var ActionBarCtrl = function($scope, email, dialog, status) { }); }; + /** + * This method is called when the user changes the searchText + */ + $scope.displaySearchResults = function(searchText) { + $scope.$root.$broadcast('search', searchText); + }; + + // + // scope state + // + // share local scope functions with root state $scope.state.actionBar = { markMessage: $scope.markMessage, flagMessage: $scope.flagMessage }; + // + // Helper functions + // + function currentFolder() { return $scope.state.nav.currentFolder; } @@ -223,13 +254,6 @@ var ActionBarCtrl = function($scope, email, dialog, status) { return message.checked; }); } - - /** - * This method is called when the user changes the searchText - */ - $scope.displaySearchResults = function(searchText) { - $scope.$root.$broadcast('search', searchText); - }; }; module.exports = ActionBarCtrl; \ No newline at end of file diff --git a/src/js/controller/app/contacts.js b/src/js/controller/app/contacts.js index 58bd3d4..e208706 100644 --- a/src/js/controller/app/contacts.js +++ b/src/js/controller/app/contacts.js @@ -4,7 +4,7 @@ // Controller // -var ContactsCtrl = function($scope, keychain, pgp, dialog) { +var ContactsCtrl = function($scope, $q, keychain, pgp, dialog) { // // scope state @@ -13,7 +13,7 @@ var ContactsCtrl = function($scope, keychain, pgp, dialog) { $scope.state.contacts = { toggle: function(to) { $scope.state.lightbox = (to) ? 'contacts' : undefined; - $scope.listKeys(); + return $scope.listKeys(); } }; @@ -22,22 +22,21 @@ var ContactsCtrl = function($scope, keychain, pgp, dialog) { // $scope.listKeys = function() { - keychain.listLocalPublicKeys(function(err, keys) { - if (err) { - dialog.error(err); - return; - } + return $q(function(resolve) { + resolve(); - keys.forEach(addParams); + }).then(function() { + return keychain.listLocalPublicKeys(); - $scope.keys = keys; - $scope.$apply(); - - function addParams(key) { + }).then(function(keys) { + // add params to key objects + keys.forEach(function(key) { var params = pgp.getKeyParams(key.publicKey); _.extend(key, params); - } - }); + }); + $scope.keys = keys; + + }).catch(dialog.error); }; $scope.getFingerprint = function(key) { @@ -74,27 +73,17 @@ var ContactsCtrl = function($scope, keychain, pgp, dialog) { imported: true // mark manually imported keys }; - keychain.saveLocalPublicKey(pubkey, function(err) { - if (err) { - dialog.error(err); - return; - } - + return keychain.saveLocalPublicKey(pubkey).then(function() { // update displayed keys - $scope.listKeys(); - }); + return $scope.listKeys(); + }).catch(dialog.error); }; $scope.removeKey = function(key) { - keychain.removeLocalPublicKey(key._id, function(err) { - if (err) { - dialog.error(err); - return; - } - + return keychain.removeLocalPublicKey(key._id).then(function() { // update displayed keys - $scope.listKeys(); - }); + return $scope.listKeys(); + }).catch(dialog.error); }; }; diff --git a/src/js/controller/app/mail-list.js b/src/js/controller/app/mail-list.js index a3ec8d6..eb333b4 100644 --- a/src/js/controller/app/mail-list.js +++ b/src/js/controller/app/mail-list.js @@ -11,7 +11,7 @@ var INIT_DISPLAY_LEN = 50, FOLDER_TYPE_INBOX = 'Inbox', NOTIFICATION_INBOX_TIMEOUT = 5000; -var MailListCtrl = function($scope, $timeout, $location, $filter, status, notification, email, keychain, dialog, search, dummy) { +var MailListCtrl = function($scope, $timeout, $location, $filter, $q, status, notification, email, keychain, dialog, search, dummy) { // // scope state @@ -55,23 +55,26 @@ var MailListCtrl = function($scope, $timeout, $location, $filter, status, notifi // $scope.getBody = function(message) { - email.getBody({ - folder: currentFolder(), - message: message - }, function(err) { - if (err && err.code !== 42) { - dialog.error(err); - return; - } + return $q(function(resolve) { + resolve(); - // display fetched body - $scope.$digest(); + }).then(function() { + return email.getBody({ + folder: currentFolder(), + message: message + }); + }).then(function() { // automatically decrypt if it's the selected message if (message === currentMessage()) { - email.decryptBody({ + return email.decryptBody({ message: message - }, dialog.error); + }); + } + + }).catch(function(err) { + if (err.code !== 42) { + dialog.error(err); } }); }; @@ -93,19 +96,20 @@ var MailListCtrl = function($scope, $timeout, $location, $filter, status, notifi return; } - keychain.refreshKeyForUserId({ - userId: message.from[0].address - }, onKeyRefreshed); + return $q(function(resolve) { + resolve(); - function onKeyRefreshed(err) { - if (err) { - dialog.error(err); - } + }).then(function() { + return keychain.refreshKeyForUserId({ + userId: message.from[0].address + }); - email.decryptBody({ + }).then(function() { + return email.decryptBody({ message: message - }, dialog.error); + }); + }).then(function() { // if the message is unread, please sync the new state. // otherweise forget about it. if (!message.unread) { @@ -119,12 +123,13 @@ var MailListCtrl = function($scope, $timeout, $location, $filter, status, notifi } } - $scope.state.actionBar.markMessage(message, false, true); - } + return $scope.state.actionBar.markMessage(message, false, true); + + }).catch(dialog.error); }; $scope.flag = function(message, flagged) { - $scope.state.actionBar.flagMessage(message, flagged); + return $scope.state.actionBar.flagMessage(message, flagged); }; /** @@ -164,7 +169,7 @@ var MailListCtrl = function($scope, $timeout, $location, $filter, status, notifi } // display and select first - openCurrentFolder(); + return openCurrentFolder(); }); $scope.watchMessages = $scope.$watchCollection('state.nav.currentFolder.messages', function(messages) { @@ -246,10 +251,10 @@ var MailListCtrl = function($scope, $timeout, $location, $filter, status, notifi */ $scope.watchOnline = $scope.$watch('account.online', function(isOnline) { // wait one cycle for the status display controllers to init - $timeout(function() { + return $timeout(function() { if (isOnline) { status.update('Online'); - openCurrentFolder(); + return openCurrentFolder(); } else { status.update('Offline mode'); } @@ -265,18 +270,24 @@ var MailListCtrl = function($scope, $timeout, $location, $filter, status, notifi return; } - email.openFolder({ - folder: currentFolder() - }, function(error) { + return $q(function(resolve) { + resolve(); + + }).then(function() { + return email.openFolder({ + folder: currentFolder() + }).catch(function(err) { + // don't display err for offline case + if (err.code !== 42) { + throw err; + } + }); + + }).then(function() { // dont wait until scroll to load visible mail bodies $scope.loadVisibleBodies(); - // don't display error for offline case - if (error && error.code === 42) { - return; - } - dialog.error(error); - }); + }).catch(dialog.error); } function currentFolder() { diff --git a/src/js/controller/app/navigation.js b/src/js/controller/app/navigation.js index abc2826..c2b157a 100644 --- a/src/js/controller/app/navigation.js +++ b/src/js/controller/app/navigation.js @@ -11,7 +11,7 @@ var NOTIFICATION_SENT_TIMEOUT = 2000; // Controller // -var NavigationCtrl = function($scope, $location, account, email, outbox, notification, appConfig, dialog, dummy) { +var NavigationCtrl = function($scope, $location, $q, account, email, outbox, notification, appConfig, dialog, dummy) { if (!$location.search().dev && !account.isLoggedIn()) { $location.path('/'); // init app return; @@ -102,13 +102,19 @@ var NavigationCtrl = function($scope, $location, account, email, outbox, notific }); ob.count = count; - email.refreshFolder({ - folder: ob - }, dialog.error); + return $q(function(resolve) { + resolve(); + + }).then(function() { + return email.refreshFolder({ + folder: ob + }); + + }).catch(dialog.error); }; $scope.logout = function() { - dialog.confirm({ + return dialog.confirm({ title: str.logoutTitle, message: str.logoutMessage, callback: function(confirm) { diff --git a/src/js/controller/app/privatekey-upload.js b/src/js/controller/app/privatekey-upload.js index f8c8f9d..74e0ebc 100644 --- a/src/js/controller/app/privatekey-upload.js +++ b/src/js/controller/app/privatekey-upload.js @@ -2,7 +2,7 @@ var util = require('crypto-lib').util; -var PrivateKeyUploadCtrl = function($scope, keychain, pgp, dialog, auth) { +var PrivateKeyUploadCtrl = function($scope, $q, keychain, pgp, dialog, auth) { // // scope state @@ -19,16 +19,15 @@ var PrivateKeyUploadCtrl = function($scope, keychain, pgp, dialog, auth) { // show syncing status $scope.step = 4; // check if key is already synced - $scope.checkServerForKey(function(privateKeySynced) { + return $scope.checkServerForKey().then(function(privateKeySynced) { if (privateKeySynced) { // close lightbox $scope.state.lightbox = undefined; // show message - dialog.info({ + return dialog.info({ title: 'Info', message: 'Your PGP key has already been synced.' }); - return; } // show sync ui if key is not synced @@ -41,24 +40,19 @@ var PrivateKeyUploadCtrl = function($scope, keychain, pgp, dialog, auth) { // scope functions // - $scope.checkServerForKey = function(callback) { + $scope.checkServerForKey = function() { var keyParams = pgp.getKeyParams(); - keychain.hasPrivateKey({ - userId: keyParams.userId, - keyId: keyParams._id - }, function(err, privateKeySynced) { - if (err) { - dialog.error(err); - return; - } - if (privateKeySynced) { - callback(privateKeySynced); - return; - } + return $q(function(resolve) { + resolve(); - callback(); - }); + }).then(function() { + return keychain.hasPrivateKey({ + userId: keyParams.userId, + keyId: keyParams._id + }); + + }).catch(dialog.error); }; $scope.displayUploadUi = function() { @@ -82,29 +76,37 @@ var PrivateKeyUploadCtrl = function($scope, keychain, pgp, dialog, auth) { return true; }; - $scope.setDeviceName = function(callback) { - keychain.setDeviceName($scope.deviceName, callback); + $scope.setDeviceName = function() { + return $q(function(resolve) { + resolve(); + + }).then(function() { + return keychain.setDeviceName($scope.deviceName); + }); }; - $scope.encryptAndUploadKey = function(callback) { + $scope.encryptAndUploadKey = function() { var userId = auth.emailAddress; var code = $scope.code; // register device to keychain service - keychain.registerDevice({ - userId: userId - }, function(err) { - if (err) { - dialog.error(err); - return; - } + return $q(function(resolve) { + resolve(); + }).then(function() { + // register the device + return keychain.registerDevice({ + userId: userId + }); + + }).then(function() { // encrypt private PGP key using code and upload - keychain.uploadPrivateKey({ + return keychain.uploadPrivateKey({ userId: userId, code: code - }, callback); - }); + }); + + }).catch(dialog.error); }; $scope.goBack = function() { @@ -126,32 +128,22 @@ var PrivateKeyUploadCtrl = function($scope, keychain, pgp, dialog, auth) { if ($scope.step === 3) { // set device name to local storage - $scope.setDeviceName(function(err) { - if (err) { - dialog.error(err); - return; - } - + return $scope.setDeviceName().then(function() { // show spinner $scope.step++; - $scope.$apply(); - // init key sync - $scope.encryptAndUploadKey(function(err) { - if (err) { - dialog.error(err); - return; - } + return $scope.encryptAndUploadKey(); - // close sync dialog - $scope.state.privateKeyUpload.toggle(false); - // show success message - dialog.info({ - title: 'Success', - message: 'Whiteout Keychain setup successful!' - }); + }).then(function() { + // close sync dialog + $scope.state.privateKeyUpload.toggle(false); + // show success message + dialog.info({ + title: 'Success', + message: 'Whiteout Keychain setup successful!' }); - }); + + }).catch(dialog.error); } }; diff --git a/src/js/controller/app/read.js b/src/js/controller/app/read.js index af394fc..5222b8d 100644 --- a/src/js/controller/app/read.js +++ b/src/js/controller/app/read.js @@ -4,7 +4,7 @@ // Controller // -var ReadCtrl = function($scope, $location, email, invitation, outbox, pgp, keychain, appConfig, download, auth, dialog) { +var ReadCtrl = function($scope, $location, $q, email, invitation, outbox, pgp, keychain, appConfig, download, auth, dialog) { var str = appConfig.string; @@ -52,25 +52,24 @@ var ReadCtrl = function($scope, $location, email, invitation, outbox, pgp, keych return; } - $scope.keyId = 'Searching...'; - keychain.getReceiverPublicKey(address, function(err, pubkey) { - if (err) { - dialog.error(err); - return; - } + return $q(function(resolve) { + $scope.keyId = 'Searching...'; + resolve(); + }).then(function() { + return keychain.getReceiverPublicKey(address); + + }).then(function(pubkey) { if (!pubkey) { $scope.keyId = 'User has no key. Click to invite.'; - $scope.$apply(); return; } var fpr = pgp.getFingerprint(pubkey.publicKey); var formatted = fpr.slice(32); - $scope.keyId = 'PGP key: ' + formatted; - $scope.$apply(); - }); + + }).catch(dialog.error); }; $scope.$watch('state.mailList.selected', function(mail) { @@ -89,24 +88,20 @@ var ReadCtrl = function($scope, $location, email, invitation, outbox, pgp, keych function checkPublicKey(user) { user.secure = undefined; - if (!keychain) { - return; - } + return $q(function(resolve) { + resolve(); - keychain.getReceiverPublicKey(user.address, function(err, pubkey) { - if (err) { - dialog.error(err); - return; - } + }).then(function() { + return keychain.getReceiverPublicKey(user.address); - if (pubkey && pubkey.publicKey) { + }).then(function(pubkey) { + if (pubkey.publicKey) { user.secure = true; } else { user.secure = false; } - $scope.$apply(); - }); + }).catch(dialog.error); } $scope.download = function(attachment) { @@ -122,11 +117,18 @@ var ReadCtrl = function($scope, $location, email, invitation, outbox, pgp, keych var folder = $scope.state.nav.currentFolder; var message = $scope.state.mailList.selected; - email.getAttachment({ - folder: folder, - uid: message.uid, - attachment: attachment - }, dialog.error); + + return $q(function(resolve) { + resolve(); + + }).then(function() { + return email.getAttachment({ + folder: folder, + uid: message.uid, + attachment: attachment + }); + + }).catch(dialog.error); }; $scope.invite = function(user) { @@ -135,20 +137,20 @@ var ReadCtrl = function($scope, $location, email, invitation, outbox, pgp, keych return; } - $scope.keyId = 'Sending invitation...'; - var sender = auth.emailAddress, recipient = user.address; - invitation.invite({ - recipient: recipient, - sender: sender - }, function(err) { - if (err) { - dialog.error(err); - return; - } + return $q(function(resolve) { + $scope.keyId = 'Sending invitation...'; + resolve(); + }).then(function() { + return invitation.invite({ + recipient: recipient, + sender: sender + }); + + }).then(function() { var invitationMail = { from: [{ address: sender @@ -161,10 +163,10 @@ var ReadCtrl = function($scope, $location, email, invitation, outbox, pgp, keych subject: str.invitationSubject, body: str.invitationMessage }; - // send invitation mail - outbox.put(invitationMail, dialog.error); - }); + return outbox.put(invitationMail); + + }).catch(dialog.error); }; }; diff --git a/src/js/controller/app/set-passphrase.js b/src/js/controller/app/set-passphrase.js index acbe04b..ad2fb1d 100644 --- a/src/js/controller/app/set-passphrase.js +++ b/src/js/controller/app/set-passphrase.js @@ -1,6 +1,6 @@ 'use strict'; -var SetPassphraseCtrl = function($scope, pgp, keychain, dialog) { +var SetPassphraseCtrl = function($scope, $q, pgp, keychain, dialog) { // // scope variables @@ -76,52 +76,44 @@ var SetPassphraseCtrl = function($scope, pgp, keychain, dialog) { $scope.setPassphrase = function() { var keyId = pgp.getKeyParams()._id; - keychain.lookupPrivateKey(keyId, function(err, savedKey) { - if (err) { - dialog.error(err); - return; - } - pgp.changePassphrase({ + return $q(function(resolve) { + resolve(); + + }).then(function() { + return keychain.lookupPrivateKey(keyId); + + }).then(function(savedKey) { + // change passphrase + return pgp.changePassphrase({ privateKeyArmored: savedKey.encryptedKey, oldPassphrase: $scope.oldPassphrase, newPassphrase: $scope.newPassphrase - }, onPassphraseChanged); - }); + }).catch(function(err) { + err.showBugReporter = false; + throw err; + }); + + }).then(function(newPrivateKeyArmored) { + // persist new armored key + var keyParams = pgp.getKeyParams(newPrivateKeyArmored); + var privateKey = { + _id: keyParams._id, + userId: keyParams.userId, + userIds: keyParams.userIds, + encryptedKey: newPrivateKeyArmored + }; + return keychain.saveLocalPrivateKey(privateKey); + + }).then(function() { + $scope.state.setPassphrase.toggle(false); + return dialog.info({ + title: 'Success', + message: 'Passphrase change complete.' + }); + + }).catch(dialog.error); }; - - function onPassphraseChanged(err, newPrivateKeyArmored) { - if (err) { - err.showBugReporter = false; - dialog.error(err); - return; - } - - // persist new armored key - var keyParams = pgp.getKeyParams(newPrivateKeyArmored); - var privateKey = { - _id: keyParams._id, - userId: keyParams.userId, - userIds: keyParams.userIds, - encryptedKey: newPrivateKeyArmored - }; - - keychain.saveLocalPrivateKey(privateKey, onKeyPersisted); - } - - function onKeyPersisted(err) { - if (err) { - dialog.error(err); - return; - } - - $scope.state.setPassphrase.toggle(false); - $scope.$apply(); - dialog.info({ - title: 'Success', - message: 'Passphrase change complete.' - }); - } }; module.exports = SetPassphraseCtrl; \ No newline at end of file diff --git a/src/js/controller/app/write.js b/src/js/controller/app/write.js index ab94d2a..636fb78 100644 --- a/src/js/controller/app/write.js +++ b/src/js/controller/app/write.js @@ -218,34 +218,31 @@ var WriteCtrl = function($scope, $window, $filter, $q, appConfig, auth, keychain return; } - // keychain is undefined in local dev environment - if (keychain) { - // check if to address is contained in known public keys - // when we write an email, we always need to work with the latest keys available - keychain.refreshKeyForUserId({ + // check if to address is contained in known public keys + // when we write an email, we always need to work with the latest keys available + return $q(function(resolve) { + resolve(); + + }).then(function() { + return keychain.refreshKeyForUserId({ userId: recipient.address - }, function(err, key) { - if (err) { - dialog.error(err); - return; - } - - if (key) { - // compare again since model could have changed during the roundtrip - var matchingUserId = _.findWhere(key.userIds, { - emailAddress: recipient.address - }); - // compare either primary userId or (if available) multiple IDs - if (key.userId === recipient.address || matchingUserId) { - recipient.key = key; - recipient.secure = true; - } - } - - $scope.checkSendStatus(); - $scope.$digest(); }); - } + + }).then(function(key) { + if (key) { + // compare again since model could have changed during the roundtrip + var matchingUserId = _.findWhere(key.userIds, { + emailAddress: recipient.address + }); + // compare either primary userId or (if available) multiple IDs + if (key.userId === recipient.address || matchingUserId) { + recipient.key = key; + recipient.secure = true; + } + } + $scope.checkSendStatus(); + + }).catch(dialog.error); }; /** @@ -347,12 +344,13 @@ var WriteCtrl = function($scope, $window, $filter, $q, appConfig, auth, keychain } // persist the email to disk for later sending - outbox.put(message, function(err) { - if (err) { - dialog.error(err); - return; - } + return $q(function(resolve) { + resolve(); + }).then(function() { + return outbox.put(message); + + }).then(function() { // if we need to synchronize replyTo.answered = true to imap, // let's do that. otherwise, we're done if (!$scope.replyTo || $scope.replyTo.answered) { @@ -360,20 +358,16 @@ var WriteCtrl = function($scope, $window, $filter, $q, appConfig, auth, keychain } $scope.replyTo.answered = true; - email.setFlags({ + return email.setFlags({ folder: currentFolder(), message: $scope.replyTo - }, function(err) { - if (err && err.code !== 42) { - dialog.error(err); - return; - } - - // offline or no error, let's apply the ui changes - $scope.$apply(); }); - }); + }).catch(function(err) { + if (err.code !== 42) { + dialog.error(err); + } + }); }; // @@ -389,37 +383,29 @@ var WriteCtrl = function($scope, $window, $filter, $q, appConfig, auth, keychain }; $scope.lookupAddressBook = function(query) { - var deferred = $q.defer(); + return $q(function(resolve) { + resolve(); - if (!$scope.addressBookCache) { + }).then(function() { + if ($scope.addressBookCache) { + return; + } // populate address book cache - keychain.listLocalPublicKeys(function(err, keys) { - if (err) { - dialog.error(err); - return; - } - + return keychain.listLocalPublicKeys().then(function(keys) { $scope.addressBookCache = keys.map(function(key) { return { address: key.userId }; }); - filter(); }); - } else { - filter(); - } - - // query address book cache - function filter() { - var addresses = $scope.addressBookCache.filter(function(i) { + }).then(function() { + // filter the address book cache + return $scope.addressBookCache.filter(function(i) { return i.address.indexOf(query) !== -1; }); - deferred.resolve(addresses); - } - return deferred.promise; + }).catch(dialog.error); }; //