From 371440a79b5d586ae2350ca8fdda56c0d5319727 Mon Sep 17 00:00:00 2001 From: Christoph Wurst Date: Tue, 20 Sep 2016 13:42:06 +0200 Subject: [PATCH 01/10] allow moving messages inside a single account --- appinfo/routes.php | 4 ++++ lib/Account.php | 7 +++++++ lib/Controller/MessagesController.php | 23 ++++++++++++++++++++++ lib/Service/AccountService.php | 23 ++++++++++++++++++++-- lib/Service/IAccount.php | 7 +++++++ lib/Service/UnifiedAccount.php | 11 +++++++++-- lib/exception/serviceexception.php | 28 +++++++++++++++++++++++++++ 7 files changed, 99 insertions(+), 4 deletions(-) create mode 100644 lib/exception/serviceexception.php diff --git a/appinfo/routes.php b/appinfo/routes.php index 48d21a1f20..b9be6cc940 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -45,6 +45,10 @@ 'name' => 'messages#setFlags', 'url' => '/accounts/{accountId}/folders/{folderId}/messages/{messageId}/flags', 'verb' => 'PUT'], + [ + 'name' => 'messages#move', + 'url' => '/accounts/{accountId}/folders/{folderId}/messages/{id}/move', + 'verb' => 'POST'], [ 'name' => 'proxy#redirect', 'url' => '/redirect', diff --git a/lib/Account.php b/lib/Account.php index b9d2488355..8d4ace8634 100644 --- a/lib/Account.php +++ b/lib/Account.php @@ -518,6 +518,13 @@ public function deleteMessage($sourceFolderId, $messageId) { } } + public function moveMessage($sourceFolderId, $messageId, $destFolderId) { + $this->getImapConnection()->copy($sourceFolderId, $destFolderId, [ + 'ids' => new \Horde_Imap_Client_Ids($messageId), + 'move' => true, + ]); + } + /** * * @param int $messageId diff --git a/lib/Controller/MessagesController.php b/lib/Controller/MessagesController.php index 72951665f6..13990b9944 100755 --- a/lib/Controller/MessagesController.php +++ b/lib/Controller/MessagesController.php @@ -28,6 +28,7 @@ namespace OCA\Mail\Controller; +use OCA\Mail\Exception\ServiceException; use OCA\Mail\Http\AttachmentDownloadResponse; use OCA\Mail\Http\HtmlResponse; use OCA\Mail\Service\AccountService; @@ -203,6 +204,28 @@ public function show($accountId, $folderId, $id) { return new JSONResponse($json); } + /** + * @NoAdminRequired + * @NoCSRFRequired + * + * @param int $accountId + * @param string $folderId + * @param int $id + * @param int $destAccountId + * @param string $destFolderId + * @return JSONResponse + */ + public function move($accountId, $folderId, $id, $destAccountId, $destFolderId) { + try { + $this->accountService->moveMessage($accountId, $folderId, $id, $destAccountId, $destFolderId, $this->currentUserId); + } catch (ServiceException $ex) { + return new JSONResponse([ + 'error' => $ex->getMessage(), + ], 500); + } + return new JSONResponse(); + } + /** * @NoAdminRequired * @NoCSRFRequired diff --git a/lib/Service/AccountService.php b/lib/Service/AccountService.php index 808c493d33..d1931ea840 100644 --- a/lib/Service/AccountService.php +++ b/lib/Service/AccountService.php @@ -23,12 +23,14 @@ use Exception; use OCA\Mail\Account; +use OCA\Mail\Db\MailAccount; use OCA\Mail\Db\MailAccountMapper; +use OCA\Mail\Exception\ServiceException; use OCP\IL10N; class AccountService { - /** @var \OCA\Mail\Db\MailAccountMapper */ + /** @var MailAccountMapper */ private $mapper; /** @@ -90,6 +92,23 @@ public function find($currentUserId, $accountId) { return new Account($this->mapper->find($currentUserId, $accountId)); } + private function moveMessageOnSameAccount(IAccount $account, $sourceFolderId, + $destFolderId, $messageId) { + $account->moveMessage(base64_decode($sourceFolderId), $messageId, base64_decode($destFolderId)); + } + + public function moveMessage($accountId, $folderId, $id, $destAccountId, + $destFolderId, $userId) { + $sourceAccount = $this->find($userId, $accountId); + $destAccount = $this->find($userId, $destAccountId); + + if ($sourceAccount->getId() === $destAccount->getId()) { + $this->moveMessageOnSameAccount($sourceAccount, $folderId, $destFolderId, $id); + } else { + throw new ServiceException('It is not possible to move across accounts yet'); + } + } + /** * @param int $accountId */ @@ -103,7 +122,7 @@ public function delete($currentUserId, $accountId) { /** * @param $newAccount - * @return \OCA\Mail\Db\MailAccount + * @return MailAccount */ public function save($newAccount) { return $this->mapper->save($newAccount); diff --git a/lib/Service/IAccount.php b/lib/Service/IAccount.php index 2515f4663c..10cf956b92 100644 --- a/lib/Service/IAccount.php +++ b/lib/Service/IAccount.php @@ -61,6 +61,13 @@ public function saveDraft(IMessage $message, $previousUID); */ public function deleteMessage($folderId, $messageId); + /** + * @param string $sourceFolderId + * @param int $messageId + * @param string $destFolderId + */ + public function moveMessage($sourceFolderId, $messageId, $destFolderId); + /** * @param string[] $query * @return array diff --git a/lib/Service/UnifiedAccount.php b/lib/Service/UnifiedAccount.php index fd1c51a1ed..5afe776bab 100644 --- a/lib/Service/UnifiedAccount.php +++ b/lib/Service/UnifiedAccount.php @@ -21,8 +21,11 @@ */ namespace OCA\Mail\Service; -use OCP\IL10N; +use Exception; +use Horde_Mail_Rfc822_List; +use OCA\Mail\Exception\ServiceException; use OCA\Mail\Model\IMessage; +use OCP\IL10N; class UnifiedAccount implements IAccount { @@ -126,7 +129,7 @@ public function getMailbox($folderId) { public function getEmail() { if ($this->email === null) { $allAccounts = $this->accountService->findByUserId($this->userId); - $addressesList = new \Horde_Mail_Rfc822_List(); + $addressesList = new Horde_Mail_Rfc822_List(); foreach ($allAccounts as $account) { $inbox = $account->getInbox(); if (is_null($inbox)) { @@ -169,6 +172,10 @@ public function deleteMessage($folderId, $messageId) { $account->deleteMessage($inbox->getFolderId(), $messageId); } + public function moveMessage($sourceFolderId, $messageId, $destFolderId) { + throw new ServiceException('Not implemented'); + } + /** * @param string[] $query * @return array diff --git a/lib/exception/serviceexception.php b/lib/exception/serviceexception.php new file mode 100644 index 0000000000..c7e09a9136 --- /dev/null +++ b/lib/exception/serviceexception.php @@ -0,0 +1,28 @@ + + * + * 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 + * + */ + +namespace OCA\Mail\Exception; + +use Exception; + +class ServiceException extends Exception { + +} From f8163504e6f8d218a6907c70098347262608101d Mon Sep 17 00:00:00 2001 From: Christoph Wurst Date: Tue, 20 Sep 2016 17:10:46 +0200 Subject: [PATCH 02/10] add drag-and-drop functionality --- js/controller/messagecontroller.js | 23 ++++++++++++++++++++ js/service/messageservice.js | 35 ++++++++++++++++++++++++++++++ js/views/folderview.js | 9 ++++++++ js/views/messagesitem.js | 19 ++++++++++++++++ 4 files changed, 86 insertions(+) diff --git a/js/controller/messagecontroller.js b/js/controller/messagecontroller.js index 5ea595a2ed..00e9057155 100644 --- a/js/controller/messagecontroller.js +++ b/js/controller/messagecontroller.js @@ -32,6 +32,7 @@ define(function(require) { }); Radio.message.on('forward', openForwardComposer); Radio.message.on('flag', flagMessage); + Radio.message.on('move', moveMessage); /** * @param {Account} account @@ -189,6 +190,28 @@ define(function(require) { }); } + function moveMessage(sourceAccount, sourceFolder, message, destAccount, + destFolder) { + if (sourceAccount.get('accountId') === destAccount.get('accountId') + && sourceFolder.get('id') === destFolder.get('id')) { + // Nothing to move + return; + } + + var moving = Radio.message.request('move', sourceAccount, sourceFolder, message, destAccount, destFolder); + + sourceFolder.get('messages').remove(message); + + $.when(moving).done(function() { + // TODO: update counters + + }); + $.when(moving).fail(function() { + Radio.ui.trigger('error:show', t('mail', 'Could not move message.')); + sourceFolder.get('messages').add(message); + }); + } + /** * @param {Account} account * @param {Folder} folder diff --git a/js/service/messageservice.js b/js/service/messageservice.js index dd28fdce45..76a19f1de5 100644 --- a/js/service/messageservice.js +++ b/js/service/messageservice.js @@ -29,6 +29,7 @@ define(function(require) { Radio.message.reply('entity', getMessageEntity); Radio.message.reply('bodies', fetchMessageBodies); Radio.message.reply('flag', flagMessage); + Radio.message.reply('move', moveMessage); Radio.message.reply('send', sendMessage); Radio.message.reply('draft', saveDraft); Radio.message.reply('delete', deleteMessage); @@ -206,6 +207,40 @@ define(function(require) { return defer.promise(); } + /** + * @param {Account} sourceAccount + * @param {Folder} sourceFolder + * @param {Message} message + * @param {Account} destAccount + * @param {Folder} destFolder + * @returns {Deferred} + */ + function moveMessage(sourceAccount, sourceFolder, message, destAccount, + destFolder) { + var defer = $.Deferred(); + + var url = OC.generateUrl('apps/mail/accounts/{accountId}/folders/{folderId}/messages/{messageId}/move', { + accountId: sourceAccount.get('accountId'), + folderId: sourceFolder.get('id'), + messageId: message.get('id') + }); + $.ajax(url, { + type: 'POST', + data: { + destAccountId: destAccount.get('accountId'), + destFolderId: destFolder.get('id') + }, + success: function() { + defer.resolve(); + }, + error: function() { + defer.reject(); + } + }); + + return defer.promise(); + } + /** * @param {Account} account * @param {object} message diff --git a/js/views/folderview.js b/js/views/folderview.js index d86c16090e..9b7d621c07 100644 --- a/js/views/folderview.js +++ b/js/views/folderview.js @@ -94,6 +94,15 @@ define(function(require) { })); this.updateElClasses(); + + this.$el.droppable({ + drop: _.bind(function(event, ui) { + var account = require('state').currentAccount; + var sourceFolder = account.getFolderById(ui.helper.data('folderId')); + var message = sourceFolder.get('messages').get(ui.helper.data('messageId')); + Radio.message.trigger('move', account, sourceFolder, message, account, this.model); + }, this) + }); } }); }); diff --git a/js/views/messagesitem.js b/js/views/messagesitem.js index 449ed27a68..47439d23e3 100644 --- a/js/views/messagesitem.js +++ b/js/views/messagesitem.js @@ -53,6 +53,22 @@ define(function(require) { }); } + var _this = this; + this.$el.draggable({ + appendTo: '#content-wrapper', + helper: function() { + var el = $('
'); + el.data('folderId', require('state').currentFolder.get('id')); + el.data('messageId', _this.model.get('id')); + return el; + }, + cursorAt: { + top: -5, + left: -5 + }, + revert: true + }); + $('.action.delete').tooltip({placement: 'left'}); }, toggleMessageStar: function(event) { @@ -137,6 +153,9 @@ define(function(require) { count = folder.get('total'); folder.set('total', count + 1); }); + }, + onDrag: function(event) { + console.log(event); } }); }); From 14351930e8ce237b89ef92af6634d7c9312af576 Mon Sep 17 00:00:00 2001 From: Christoph Wurst Date: Tue, 20 Sep 2016 18:14:56 +0200 Subject: [PATCH 03/10] show visual feedback if a message can be dropped onto a folder --- css/mail.css | 4 ++++ js/views/folderview.js | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/css/mail.css b/css/mail.css index e08562a9f7..641022315a 100755 --- a/css/mail.css +++ b/css/mail.css @@ -26,6 +26,10 @@ border: none; } +.mail_folders > .ui-droppable-active { + background-color: rgb(240, 240, 240); +} + /* SETUP */ #setup { diff --git a/js/views/folderview.js b/js/views/folderview.js index 9b7d621c07..2a0526404c 100644 --- a/js/views/folderview.js +++ b/js/views/folderview.js @@ -101,7 +101,8 @@ define(function(require) { var sourceFolder = account.getFolderById(ui.helper.data('folderId')); var message = sourceFolder.get('messages').get(ui.helper.data('messageId')); Radio.message.trigger('move', account, sourceFolder, message, account, this.model); - }, this) + }, this), + hoverClass: 'ui-droppable-active' }); } }); From a9991facf6c5e38b7b25c0a9f9e0835e3ed2bf1b Mon Sep 17 00:00:00 2001 From: Christoph Wurst Date: Wed, 21 Sep 2016 11:59:19 +0200 Subject: [PATCH 04/10] add scope to draggable/droppable to prevent cross-account drags --- js/controller/messagecontroller.js | 6 +++--- js/models/account.js | 2 +- js/models/folder.js | 5 ++++- js/models/message.js | 6 ++++++ js/service/folderservice.js | 3 ++- js/views/folderview.js | 4 +++- js/views/messagesitem.js | 5 ++--- js/views/messagesview.js | 3 ++- 8 files changed, 23 insertions(+), 11 deletions(-) diff --git a/js/controller/messagecontroller.js b/js/controller/messagecontroller.js index 00e9057155..302c178528 100644 --- a/js/controller/messagecontroller.js +++ b/js/controller/messagecontroller.js @@ -200,15 +200,15 @@ define(function(require) { var moving = Radio.message.request('move', sourceAccount, sourceFolder, message, destAccount, destFolder); - sourceFolder.get('messages').remove(message); + sourceFolder.messages.remove(message); + destFolder.addMessage(message); $.when(moving).done(function() { // TODO: update counters - }); $.when(moving).fail(function() { Radio.ui.trigger('error:show', t('mail', 'Could not move message.')); - sourceFolder.get('messages').add(message); + sourceFolder.addMessage(message); }); } diff --git a/js/models/account.js b/js/models/account.js index f10557b3e6..5874906ab9 100644 --- a/js/models/account.js +++ b/js/models/account.js @@ -58,8 +58,8 @@ define(function(require) { * @returns {undefined} */ addFolder: function(folder) { - folder = this.folders.add(folder); folder.account = this; + this.folders.add(folder); }, getFolderById: function(folderId) { if (!this.folders) { diff --git a/js/models/folder.js b/js/models/folder.js index 84fd0e1c0e..93f3668107 100644 --- a/js/models/folder.js +++ b/js/models/folder.js @@ -30,7 +30,10 @@ define(function(require) { initialize: function() { var FolderCollection = require('models/foldercollection'); var MessageCollection = require('models/messagecollection'); + this.account = this.get('account'); + this.unset('account'); this.folders = new FolderCollection(this.get('folders') || []); + this.unset('folders'); this.messages = new MessageCollection(); }, toggleOpen: function() { @@ -41,8 +44,8 @@ define(function(require) { * @returns {undefined} */ addMessage: function(message) { - this.messages.add(message); message.folder = this; + this.messages.add(message); }, /** * @param {Array} message diff --git a/js/models/message.js b/js/models/message.js index 4fb4768fcf..322f40fac6 100644 --- a/js/models/message.js +++ b/js/models/message.js @@ -18,12 +18,18 @@ define(function(require) { * @class Message */ var Message = Backbone.Model.extend({ + folder: undefined, defaults: { flags: [], active: false }, initialize: function() { this.set('flags', new MessageFlags(this.get('flags'))); + if (this.get('folder')) { + // Folder should be a simple property + this.folder = this.get('folder'); + this.unset('folder'); + } this.listenTo(this.get('flags'), 'change', this._transformEvent); }, _transformEvent: function() { diff --git a/js/service/folderservice.js b/js/service/folderservice.js index a5be63ae6d..facc31ed0b 100644 --- a/js/service/folderservice.js +++ b/js/service/folderservice.js @@ -12,6 +12,7 @@ define(function(require) { 'use strict'; var $ = require('jquery'); + var _ = require('underscore'); var OC = require('OC'); /** @@ -32,7 +33,7 @@ define(function(require) { for (var prop in data) { if (prop === 'folders') { account.folders.reset(); - account.addFolder(data.folders); + _.each(data.folders, account.addFolder, account); } else { account.set(prop, data[prop]); } diff --git a/js/views/folderview.js b/js/views/folderview.js index 2a0526404c..0cd3fa2e0b 100644 --- a/js/views/folderview.js +++ b/js/views/folderview.js @@ -95,11 +95,13 @@ define(function(require) { this.updateElClasses(); + var dropScope = 'folder-' + this.model.account.get('accountId'); this.$el.droppable({ + scope: dropScope, drop: _.bind(function(event, ui) { var account = require('state').currentAccount; var sourceFolder = account.getFolderById(ui.helper.data('folderId')); - var message = sourceFolder.get('messages').get(ui.helper.data('messageId')); + var message = sourceFolder.messages.get(ui.helper.data('messageId')); Radio.message.trigger('move', account, sourceFolder, message, account, this.model); }, this), hoverClass: 'ui-droppable-active' diff --git a/js/views/messagesitem.js b/js/views/messagesitem.js index 47439d23e3..4874f1cda5 100644 --- a/js/views/messagesitem.js +++ b/js/views/messagesitem.js @@ -54,8 +54,10 @@ define(function(require) { } var _this = this; + var dragScope = 'folder-' + this.model.folder.account.get('accountId'); this.$el.draggable({ appendTo: '#content-wrapper', + scope: dragScope, helper: function() { var el = $('
'); el.data('folderId', require('state').currentFolder.get('id')); @@ -153,9 +155,6 @@ define(function(require) { count = folder.get('total'); folder.set('total', count + 1); }); - }, - onDrag: function(event) { - console.log(event); } }); }); diff --git a/js/views/messagesview.js b/js/views/messagesview.js index 206ab7930e..d4856a6b20 100644 --- a/js/views/messagesview.js +++ b/js/views/messagesview.js @@ -242,7 +242,8 @@ define(function(require) { replace: reload }); - $.when(loadingMessages).done(function() { + $.when(loadingMessages).done(function(a) { + console.log(a); Radio.ui.trigger('messagesview:message:setactive', require('state').currentMessage); }); From 167574b9e8f397c55d4214445a2c59d92b9654b6 Mon Sep 17 00:00:00 2001 From: Christoph Wurst Date: Wed, 21 Sep 2016 13:16:53 +0200 Subject: [PATCH 05/10] disallow dropping mail into the search folder --- js/views/folderview.js | 25 ++++++++++++++----------- js/views/messagesview.js | 3 +-- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/js/views/folderview.js b/js/views/folderview.js index 0cd3fa2e0b..7201900ea0 100644 --- a/js/views/folderview.js +++ b/js/views/folderview.js @@ -95,17 +95,20 @@ define(function(require) { this.updateElClasses(); - var dropScope = 'folder-' + this.model.account.get('accountId'); - this.$el.droppable({ - scope: dropScope, - drop: _.bind(function(event, ui) { - var account = require('state').currentAccount; - var sourceFolder = account.getFolderById(ui.helper.data('folderId')); - var message = sourceFolder.messages.get(ui.helper.data('messageId')); - Radio.message.trigger('move', account, sourceFolder, message, account, this.model); - }, this), - hoverClass: 'ui-droppable-active' - }); + // Make non search fodler folders droppable + if (!(/\/FLAGGED$/.test(atob(this.model.get('id'))))) { + var dropScope = 'folder-' + this.model.account.get('accountId'); + this.$el.droppable({ + scope: dropScope, + drop: _.bind(function(event, ui) { + var account = require('state').currentAccount; + var sourceFolder = account.getFolderById(ui.helper.data('folderId')); + var message = sourceFolder.messages.get(ui.helper.data('messageId')); + Radio.message.trigger('move', account, sourceFolder, message, account, this.model); + }, this), + hoverClass: 'ui-droppable-active' + }); + } } }); }); diff --git a/js/views/messagesview.js b/js/views/messagesview.js index d4856a6b20..206ab7930e 100644 --- a/js/views/messagesview.js +++ b/js/views/messagesview.js @@ -242,8 +242,7 @@ define(function(require) { replace: reload }); - $.when(loadingMessages).done(function(a) { - console.log(a); + $.when(loadingMessages).done(function() { Radio.ui.trigger('messagesview:message:setactive', require('state').currentMessage); }); From ad0a5bae43dd661a363b6ee788062d12a82602c5 Mon Sep 17 00:00:00 2001 From: Christoph Wurst Date: Wed, 21 Sep 2016 14:57:30 +0200 Subject: [PATCH 06/10] only wrongly dropped messages should return --- js/views/messagesitem.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/views/messagesitem.js b/js/views/messagesitem.js index 4874f1cda5..6e7a11e734 100644 --- a/js/views/messagesitem.js +++ b/js/views/messagesitem.js @@ -68,7 +68,7 @@ define(function(require) { top: -5, left: -5 }, - revert: true + revert: 'invalid' }); $('.action.delete').tooltip({placement: 'left'}); From a219bc3b6ade1210231c13e8e8d2de19bfd6896e Mon Sep 17 00:00:00 2001 From: Christoph Wurst Date: Wed, 21 Sep 2016 18:20:32 +0200 Subject: [PATCH 07/10] fix subfolders data structure --- js/models/folder.js | 8 ++++---- js/views/folderview.js | 5 ++++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/js/models/folder.js b/js/models/folder.js index 93f3668107..94ede0dff7 100644 --- a/js/models/folder.js +++ b/js/models/folder.js @@ -33,6 +33,9 @@ define(function(require) { this.account = this.get('account'); this.unset('account'); this.folders = new FolderCollection(this.get('folders') || []); + this.folders.forEach(_.bind(function(folder) { + folder.account = this.account; + }, this)); this.unset('folders'); this.messages = new MessageCollection(); }, @@ -62,14 +65,11 @@ define(function(require) { * @returns {undefined} */ addFolder: function(folder) { - folder = this.folder.add(folder); + folder = this.folders.add(folder); folder.account = this.account; }, toJSON: function() { var data = Backbone.Model.prototype.toJSON.call(this); - if (data.folders && data.folders.toJSON) { - data.folders = data.folders.toJSON(); - } if (!data.id) { data.id = this.cid; } diff --git a/js/views/folderview.js b/js/views/folderview.js index 7201900ea0..ed8fd80056 100644 --- a/js/views/folderview.js +++ b/js/views/folderview.js @@ -59,9 +59,12 @@ define(function(require) { folderId: this.model.get('id') }); + var folders = this.model.folders.length > 0 ? this.model.folders.toJSON() : undefined; + return { count: count, - url: url + url: url, + folders: folders }; }, regions: { From b641cda077129cf88151cce95b5b6a755818a681 Mon Sep 17 00:00:00 2001 From: Christoph Wurst Date: Sat, 26 Nov 2016 16:25:56 +0100 Subject: [PATCH 08/10] fix nested droppable and various other small bugs --- js/cache.js | 82 ------------------------- js/controller/foldercontroller.js | 8 +-- js/models/folder.js | 8 +-- js/views/foldercontent.js | 2 +- js/views/folderview.js | 1 + js/views/messagesview.js | 11 +--- js/views/{message.js => messageview.js} | 0 7 files changed, 9 insertions(+), 103 deletions(-) rename js/views/{message.js => messageview.js} (100%) diff --git a/js/cache.js b/js/cache.js index a386093770..194e5db9ba 100644 --- a/js/cache.js +++ b/js/cache.js @@ -43,24 +43,6 @@ define(function(require) { } }; - var FolderCache = { - /** - * @param {Account} account - * @returns {string} - */ - getAccountPath: function(account) { - return ['folders', account.get('accountId').toString()].join('.'); - }, - /** - * @param {Account} account - * @param {Folder} folder - * @returns {string} - */ - getFolderPath: function(account, folder) { - return [this.getAccountPath(account), folder.get('id').toString()].join('.'); - } - }; - function init() { console.log('initializing cache…'); var installedVersion = $('#config-installed-version').val(); @@ -96,16 +78,6 @@ define(function(require) { }); } - /** - * @param {Account} account - * @param {Folder} folder - * @returns {unresolved} - */ - function getFolderMessages(account, folder) { - var path = MessageCache.getFolderPath(account, folder); - return storage.isSet(path) ? storage.get(path) : null; - } - /** * @param {Account} account * @param {Folder} folder @@ -132,23 +104,8 @@ define(function(require) { */ function addMessage(account, folder, message) { var path = MessageCache.getMessagePath(account, folder, message.id); - // Add timestamp for later cleanup - message.timestamp = Date.now(); - // Save the message to local storage storage.set(path, message); - - // Remove old messages (keep 20 most recently loaded) - var messages = $.map(getFolderMessages(account, folder), function(value) { - return [value]; - }); - messages.sort(function(m1, m2) { - return m2.timestamp - m1.timestamp; - }); - var oldMessages = messages.slice(20, messages.length); - _.each(oldMessages, function(message) { - storage.remove(MessageCache.getMessagePath(account, folder, message.id)); - }); } /** @@ -175,39 +132,6 @@ define(function(require) { // message exists in cache -> remove it storage.remove(MessageCache.getMessagePath(account, folder, messageId)); } - var messageList = getMessageList(account, folder); - if (messageList) { - // message list is cached -> remove message from it - var newList = _.filter(messageList, function(message) { - return message.id !== messageId; - }); - addMessageList(account, folder, newList); - } - } - - /** - * @param {Account} account - * @param {Folder} folder - * @returns {unresolved} - */ - function getMessageList(account, folder) { - var path = FolderCache.getFolderPath(account, folder); - if (storage.isSet(path)) { - return storage.get(path); - } else { - return null; - } - } - - /** - * @param {Account} account - * @param {Folder} folder - * @param {type} messages - * @returns {undefined} - */ - function addMessageList(account, folder, messages) { - var path = FolderCache.getFolderPath(account, folder); - storage.set(path, messages); } /** @@ -215,12 +139,6 @@ define(function(require) { * @returns {undefined} */ function removeAccount(account) { - // Remove cached message lists - var path = FolderCache.getAccountPath(account); - if (storage.isSet(path)) { - storage.remove(path); - } - // Remove cached messages path = MessageCache.getAccountPath(account); if (storage.isSet(path)) { diff --git a/js/controller/foldercontroller.js b/js/controller/foldercontroller.js index 8bee8ecdc0..bd00e1016e 100644 --- a/js/controller/foldercontroller.js +++ b/js/controller/foldercontroller.js @@ -68,7 +68,7 @@ define(function(require) { replace: true }); - $.when(loadingMessages).done(function(messages, cached) { + $.when(loadingMessages).done(function(messages) { Radio.ui.trigger('foldercontent:show', account, folder, { searchQuery: searchQuery }); @@ -86,12 +86,6 @@ define(function(require) { Radio.message.trigger('load', account, folder, messages.first()); } - - if (cached) { - // Trigger folder update - // TODO: replace with horde sync once it's implemented - Radio.ui.trigger('messagesview:messages:update'); - } }); $.when(loadingMessages).fail(function() { diff --git a/js/models/folder.js b/js/models/folder.js index 94ede0dff7..e501511c8c 100644 --- a/js/models/folder.js +++ b/js/models/folder.js @@ -55,10 +55,10 @@ define(function(require) { * @returns {undefined} */ addMessages: function(messages) { - messages = this.messages.add(messages); - _.each(messages, function(msg) { - msg.folder = this; - }, this); + var _this = this; + _.each(messages, function(message) { + _this.addMessage(message); + }); }, /** * @param {Folder} folder diff --git a/js/views/foldercontent.js b/js/views/foldercontent.js index ed944111d0..11eaa8bda6 100644 --- a/js/views/foldercontent.js +++ b/js/views/foldercontent.js @@ -27,7 +27,7 @@ define(function(require) { var Handlebars = require('handlebars'); var Radio = require('radio'); var ComposerView = require('views/composerview'); - var MessageView = require('views/message'); + var MessageView = require('views/messageview'); var MessagesView = require('views/messagesview'); var ErrorView = require('views/errorview'); var LoadingView = require('views/loadingview'); diff --git a/js/views/folderview.js b/js/views/folderview.js index ed8fd80056..1b954655c7 100644 --- a/js/views/folderview.js +++ b/js/views/folderview.js @@ -103,6 +103,7 @@ define(function(require) { var dropScope = 'folder-' + this.model.account.get('accountId'); this.$el.droppable({ scope: dropScope, + greedy: true, drop: _.bind(function(event, ui) { var account = require('state').currentAccount; var sourceFolder = account.getFolderById(ui.helper.data('folderId')); diff --git a/js/views/messagesview.js b/js/views/messagesview.js index 206ab7930e..04444e1b8f 100644 --- a/js/views/messagesview.js +++ b/js/views/messagesview.js @@ -22,7 +22,7 @@ define(function(require) { var _ = require('underscore'); var $ = require('jquery'); - var Backbone = require('backbone'); + var Marionette = require('marionette'); var Handlebars = require('handlebars'); var Radio = require('radio'); var MessagesItemView = require('views/messagesitem'); @@ -30,7 +30,7 @@ define(function(require) { var EmptyFolderView = require('views/emptyfolderview'); var NoSearchResultView = require('views/nosearchresultmessagelistview'); - return Backbone.Marionette.CompositeView.extend({ + return Marionette.CompositeView.extend({ collection: null, $scrollContainer: undefined, childView: MessagesItemView, @@ -44,9 +44,6 @@ define(function(require) { DOMMouseScroll: 'onWheel', mousewheel: 'onWheel' }, - collectionEvents: { - update: 'render' - }, initialize: function(options) { this.searchQuery = options.searchQuery; @@ -248,10 +245,6 @@ define(function(require) { $.when(loadingMessages).fail(function() { Radio.ui.trigger('error:show', t('mail', 'Error while loading messages.')); - // Set the old folder as being active - var account = require('state').currentAccount; - var folder = require('state').currentFolder; - Radio.folder.trigger('setactive', account, folder); }); $.when(loadingMessages).always(function() { diff --git a/js/views/message.js b/js/views/messageview.js similarity index 100% rename from js/views/message.js rename to js/views/messageview.js From 3ddd82dc1fb34231dab8b42aba75353bd055b758 Mon Sep 17 00:00:00 2001 From: Christoph Wurst Date: Sat, 26 Nov 2016 16:27:10 +0100 Subject: [PATCH 09/10] fix undefined var --- js/cache.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/cache.js b/js/cache.js index 194e5db9ba..7801daa8cd 100644 --- a/js/cache.js +++ b/js/cache.js @@ -140,7 +140,7 @@ define(function(require) { */ function removeAccount(account) { // Remove cached messages - path = MessageCache.getAccountPath(account); + var path = MessageCache.getAccountPath(account); if (storage.isSet(path)) { storage.remove(path); } From d9d4e1eb222ff9a63881303b9d856d8f36c8b3c0 Mon Sep 17 00:00:00 2001 From: Christoph Wurst Date: Fri, 16 Dec 2016 16:51:58 +0100 Subject: [PATCH 10/10] fix css selector --- css/mail.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/css/mail.css b/css/mail.css index 641022315a..7b11b407a2 100755 --- a/css/mail.css +++ b/css/mail.css @@ -26,7 +26,7 @@ border: none; } -.mail_folders > .ui-droppable-active { +.folders .ui-droppable-active { background-color: rgb(240, 240, 240); }