Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/mail.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteffen Lindner <mail@steffen-lindner.de>2017-08-23 16:13:39 +0300
committerGitHub <noreply@github.com>2017-08-23 16:13:39 +0300
commite0579bd8b670134d49e38808065a6293103bc488 (patch)
tree2deb40e440068dce6d1c5b1365555ed6e7542f12
parent7ffd0d6e98b17709b1f51b22f22a29a7f8f4d515 (diff)
parent959095ded37df49af560eca2a9d6ac642ac77cb7 (diff)
Merge pull request #413 from nextcloud/refactor/background-syncnightly-20170823
Fix background synchronization
-rw-r--r--appinfo/routes.php2
-rw-r--r--js/app.js30
-rw-r--r--js/radio.js8
-rw-r--r--js/service/backgroundsyncservice.js67
-rw-r--r--js/service/foldersyncservice.js10
-rw-r--r--js/tests/service/backgroundsyncservice_spec.js49
-rw-r--r--js/util/notificationhandler.js35
-rw-r--r--js/views/messagesview.js2
-rw-r--r--lib/Account.php52
-rw-r--r--lib/Service/IAccount.php6
-rw-r--r--lib/Service/UnifiedAccount.php38
11 files changed, 175 insertions, 124 deletions
diff --git a/appinfo/routes.php b/appinfo/routes.php
index 7b8f72049..69c75d962 100644
--- a/appinfo/routes.php
+++ b/appinfo/routes.php
@@ -87,7 +87,7 @@ $app->registerRoutes($this,
],
'resources' => [
'autoComplete' => ['url' => '/autoComplete'],
- 'localAttachments' => ['url' => '/attachments'],
+ 'localAttachments' => ['url' => '/attachments'],
'accounts' => ['url' => '/accounts'],
'folders' => ['url' => '/accounts/{accountId}/folders'],
'messages' => ['url' => '/accounts/{accountId}/folders/{folderId}/messages'],
diff --git a/js/app.js b/js/app.js
index e037b9a8a..9d5d1307b 100644
--- a/js/app.js
+++ b/js/app.js
@@ -40,15 +40,22 @@ define(function(require) {
require('controller/foldercontroller');
require('controller/messagecontroller');
require('service/accountservice');
+ require('service/aliasesservice');
require('service/attachmentservice');
require('service/davservice');
require('service/folderservice');
require('service/foldersyncservice');
require('service/messageservice');
- require('service/aliasesservice');
+ require('service/backgroundsyncservice');
require('util/notificationhandler');
var Mail = Marionette.Application.extend({
+
+ /**
+ * Register the mailto protocol handler
+ *
+ * @returns {undefined}
+ */
registerProtocolHandler: function() {
if (window.navigator.registerProtocolHandler) {
var url = window.location.protocol + '//' +
@@ -61,11 +68,31 @@ define(function(require) {
}
}
},
+
+ /**
+ * @returns {undefined}
+ */
requestNotificationPermissions: function() {
Radio.ui.trigger('notification:request');
},
+
+ /**
+ * Register the actual search module in the search proxy
+ *
+ * @returns {undefined}
+ */
setUpSearch: function() {
SearchProxy.setFilter(require('search').filter);
+ },
+
+ /**
+ * Start syncing accounts in the background
+ *
+ * @param {AccountCollection} accounts
+ * @returns {undefined}
+ */
+ startBackgroundSync: function(accounts) {
+ Radio.sync.trigger('start', accounts);
}
});
@@ -87,6 +114,7 @@ define(function(require) {
controller: new RouteController(accounts)
});
Backbone.history.start();
+ _this.startBackgroundSync(accounts);
});
/**
diff --git a/js/radio.js b/js/radio.js
index c38151fa3..c26b06a1a 100644
--- a/js/radio.js
+++ b/js/radio.js
@@ -16,16 +16,17 @@ define(function(require) {
var channelNames = [
'account',
+ 'aliases',
'attachment',
'folder',
'dav',
+ 'keyboard',
'message',
'navigation',
'notification',
'state',
- 'ui',
- 'keyboard',
- 'aliases'
+ 'sync',
+ 'ui'
];
var channels = {};
@@ -37,4 +38,3 @@ define(function(require) {
return channels;
});
-
diff --git a/js/service/backgroundsyncservice.js b/js/service/backgroundsyncservice.js
new file mode 100644
index 000000000..a86d2c9aa
--- /dev/null
+++ b/js/service/backgroundsyncservice.js
@@ -0,0 +1,67 @@
+/**
+ * @author Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * Mail
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+define(function(require) {
+ 'use strict';
+
+ var Radio = require('radio');
+ var _timer = null;
+ var _accounts = null;
+
+ Radio.sync.on('start', startBackgroundSync);
+
+ var SYNC_INTERVAL = 30 * 1000; // twice a minute
+
+ function startBackgroundSync(accounts) {
+ _accounts = accounts;
+ clearTimeout(_timer);
+ triggerNextSync();
+ }
+
+ function triggerNextSync() {
+ _timer = setTimeout(function() {
+ var account;
+ if (require('state').accounts.length === 0) {
+ account = _accounts.first();
+ } else {
+ account = _accounts.get(-1);
+ }
+ sync(account);
+ }, SYNC_INTERVAL);
+ }
+
+ /**
+ * @param {Account} account
+ * @returns {Promise}
+ */
+ function sync(account) {
+ return Radio.sync.request('sync:folder', account.folders.first())
+ .then(function(newMessages) {
+ Radio.ui.trigger('notification:mail:show', newMessages);
+ })
+ .catch(function(e) {
+ console.error(e);
+ })
+ .then(triggerNextSync);
+ }
+
+ return {
+ sync: sync
+ };
+});
diff --git a/js/service/foldersyncservice.js b/js/service/foldersyncservice.js
index 927c73f70..121122c27 100644
--- a/js/service/foldersyncservice.js
+++ b/js/service/foldersyncservice.js
@@ -27,7 +27,7 @@ define(function(require) {
var OC = require('OC');
var Radio = require('radio');
- Radio.message.reply('sync', syncFolder);
+ Radio.sync.reply('sync:folder', syncFolder);
/**
* @private
@@ -86,6 +86,8 @@ define(function(require) {
folder.messages.remove(id);
});
+
+ return newMessages;
});
}
@@ -112,7 +114,11 @@ define(function(require) {
return acc.concat(f);
}, []).map(function(folder) {
return syncSingleFolder(folder, unifiedFolder);
- }));
+ })).then(function(results) {
+ return results.reduce(function(acc, newMessages) {
+ return acc.concat(newMessages);
+ }, []);
+ });
} else {
var unifiedAccount = allAccounts.get(-1);
if (unifiedAccount) {
diff --git a/js/tests/service/backgroundsyncservice_spec.js b/js/tests/service/backgroundsyncservice_spec.js
new file mode 100644
index 000000000..4d1f50a38
--- /dev/null
+++ b/js/tests/service/backgroundsyncservice_spec.js
@@ -0,0 +1,49 @@
+/* global expect, Promise, spyOn */
+
+/**
+ * @author Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * Mail
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+define([
+ 'radio',
+ 'models/account',
+ 'models/folder',
+ 'service/backgroundsyncservice'
+], function(Radio, Account, Folder, BackgroundSyncService) {
+ describe('Background sync service', function() {
+ it('fails', function(done) {
+ spyOn(Radio.sync, 'request').and.returnValue(Promise.resolve([]));
+ spyOn(Radio.ui, 'trigger');
+ var account = new Account({
+ accountId: -1,
+ isUnified: true
+ });
+ var folder = new Folder({
+ account: account
+ });
+ account.addFolder(folder);
+
+ BackgroundSyncService.sync(account).then(function() {
+ expect(Radio.sync.request).toHaveBeenCalledWith('sync:folder', folder);
+ expect(Radio.ui.trigger).
+ toHaveBeenCalledWith('notification:mail:show', []);
+ done();
+ }).catch(done.fail);
+ });
+ });
+});
diff --git a/js/util/notificationhandler.js b/js/util/notificationhandler.js
index d01c1750b..922ff7cbf 100644
--- a/js/util/notificationhandler.js
+++ b/js/util/notificationhandler.js
@@ -35,8 +35,7 @@ define(function(require) {
}
}
- /*jshint maxparams: 6 */
- function showNotification(title, body, tag, icon, account, folder) {
+ function showNotification(title, body, icon) {
// notifications not supported -> go away
if (typeof Notification === 'undefined') {
return;
@@ -50,20 +49,22 @@ define(function(require) {
title,
{
body: body,
- tag: tag,
icon: icon
}
);
notification.onclick = function() {
- Radio.navigation.trigger('folder', account.get('accountId'), folder.get('id'), false);
window.focus();
};
}
- function showMailNotification(email, folder) {
- if (Notification.permission === 'granted' && folder.messages.length > 0) {
- var from = _.map(folder.messages, function(m) {
- return m.from;
+ /**
+ * @param {array<Message>} messages
+ * @returns {undefined}
+ */
+ function showMailNotification(messages) {
+ if (Notification.permission === 'granted' && messages.length > 0) {
+ var from = _.map(messages, function(m) {
+ return m.get('from');
});
from = _.uniq(from);
if (from.length > 2) {
@@ -74,9 +75,9 @@ define(function(require) {
}
// special layout if there is only 1 new message
var body = '';
- if (folder.messages.length === 1) {
- var subject = _.map(folder.messages, function(m) {
- return m.subject;
+ if (messages.length === 1) {
+ var subject = _.map(messages, function(m) {
+ return m.get('subject');
});
body = t('mail',
'{from}\n{subject}', {
@@ -85,19 +86,15 @@ define(function(require) {
});
} else {
body = n('mail',
- '%n new message in {folderName} \nfrom {from}',
- '%n new messages in {folderName} \nfrom {from}',
- folder.messages.length, {
- folderName: folder.name,
+ '%n new message \nfrom {from}',
+ '%n new messages \nfrom {from}',
+ messages.length, {
from: from.join()
});
}
// If it's okay let's create a notification
- var State = require('state');
- var tag = 'not-' + folder.accountId + '-' + folder.name;
var icon = OC.filePath('mail', 'img', 'mail-notification.png');
- var account = State.accounts.get(folder.accountId);
- showNotification(email, body, tag, icon, account, folder.id);
+ showNotification(t('mail', 'Nextcloud Mail'), body, icon);
}
}
diff --git a/js/views/messagesview.js b/js/views/messagesview.js
index e20b2db54..fbb04cb57 100644
--- a/js/views/messagesview.js
+++ b/js/views/messagesview.js
@@ -233,7 +233,7 @@ define(function(require) {
);
var folder = require('state').currentFolder;
- return Radio.message.request('sync', folder)
+ return Radio.sync.request('sync:folder', folder)
.catch(function(e) {
console.error(e);
Radio.ui.trigger('error:show', t('mail', 'Error while refreshing messages.'));
diff --git a/lib/Account.php b/lib/Account.php
index 6a084c305..0d0896b5b 100644
--- a/lib/Account.php
+++ b/lib/Account.php
@@ -680,58 +680,6 @@ class Account implements IAccount {
}
/**
- * @param $query
- * @return array
- */
- public function getChangedMailboxes($query) {
- $imp = $this->getImapConnection();
- $allBoxes = $this->getMailboxes();
- $allBoxesMap = [];
- foreach ($allBoxes as $mb) {
- $allBoxesMap[$mb->getFolderId()] = $mb;
- }
-
- // filter non existing mailboxes
- $mailBoxNames = array_filter(array_keys($query), function($folderId) use ($allBoxesMap) {
- return isset($allBoxesMap[$folderId]);
- });
-
- $status = $imp->status($mailBoxNames);
-
- // filter for changed mailboxes
- $changedBoxes = [];
- foreach ($status as $folderId => $s) {
- $uidValidity = $query[$folderId]['uidvalidity'];
- $uidNext = $query[$folderId]['uidnext'];
-
- if ($uidNext === $s['uidnext'] &&
- $uidValidity === $s['uidvalidity']) {
- continue;
- }
- // get unread messages
- if (isset($allBoxesMap[$folderId])) {
- /** @var Mailbox $m */
- $m = $allBoxesMap[$folderId];
- $role = $m->getSpecialRole();
- if (is_null($role) || $role === 'inbox') {
- $newMessages = $m->getMessagesSince($uidNext, $s['uidnext']);
- // only trigger updates in case new messages are actually available
- if (!empty($newMessages)) {
- $changedBoxes[$folderId] = $m->serialize($this->getId(), $s);
- $changedBoxes[$folderId]['messages'] = $newMessages;
- $newUnreadMessages = array_filter($newMessages, function($m) {
- return $m['flags']['unseen'];
- });
- $changedBoxes[$folderId]['newUnReadCounter'] = count($newUnreadMessages);
- }
- }
- }
- }
-
- return $changedBoxes;
- }
-
- /**
}
/**
diff --git a/lib/Service/IAccount.php b/lib/Service/IAccount.php
index 7c476d122..c9029db4e 100644
--- a/lib/Service/IAccount.php
+++ b/lib/Service/IAccount.php
@@ -50,12 +50,6 @@ interface IAccount extends JsonSerializable {
public function moveMessage($sourceFolderId, $messageId, $destFolderId);
/**
- * @param string[] $query
- * @return array
- */
- public function getChangedMailboxes($query);
-
- /**
* @return IMailBox
*/
public function getInbox();
diff --git a/lib/Service/UnifiedAccount.php b/lib/Service/UnifiedAccount.php
index 091fbd2f2..6119575ac 100644
--- a/lib/Service/UnifiedAccount.php
+++ b/lib/Service/UnifiedAccount.php
@@ -151,44 +151,6 @@ class UnifiedAccount implements IAccount {
}
/**
- * @param string[] $query
- * @return array
- */
- public function getChangedMailboxes($query) {
- $accounts = $this->accountService->findByUserId($this->userId);
- $changedBoxes = [];
-
- foreach($accounts as $account) {
- /** @var IAccount $account */
- if ($account->getId() === UnifiedAccount::ID) {
- continue;
- }
- $inbox = $account->getInbox();
- $inboxName = $inbox->getFolderId();
- $changes = $account->getChangedMailboxes([$inboxName => [
- 'uidvalidity' => $query[self::INBOX_ID]['uidvalidity'][$account->getId()],
- 'uidnext' => $query[self::INBOX_ID]['uidnext'][$account->getId()],
- ]]);
- if (!isset($changes[$inboxName])) {
- continue;
- }
- if (!isset($changedBoxes[self::INBOX_ID])) {
- $changedBoxes[self::INBOX_ID] = $this->buildInbox();
- $changedBoxes[self::INBOX_ID]['messages'] = [];
- $changedBoxes[self::INBOX_ID]['newUnReadCounter'] = 0;
- }
- // Create special unified inbox message IDs
- foreach ($changes[$inboxName]['messages'] as &$message) {
- $id = base64_encode(json_encode([$account->getId(), $message['id']]));
- $message['id'] = $id;
- }
- $changedBoxes[self::INBOX_ID]['messages'] = array_merge($changedBoxes[self::INBOX_ID]['messages'], $changes[$inboxName]['messages']);
- $changedBoxes[self::INBOX_ID]['newUnReadCounter'] += $changes[$inboxName]['newUnReadCounter'];
- }
- return $changedBoxes;
- }
-
- /**
* @return IMailBox
*/
public function getInbox() {