diff --git a/UI/MailerUI/UIxMailFolderActions.m b/UI/MailerUI/UIxMailFolderActions.m index 9313feb17..c00cb170f 100644 --- a/UI/MailerUI/UIxMailFolderActions.m +++ b/UI/MailerUI/UIxMailFolderActions.m @@ -1,6 +1,6 @@ /* UIxMailFolderActions.m - this file is part of SOGo * - * Copyright (C) 2007-2018 Inverse inc. + * Copyright (C) 2007-2021 Inverse inc. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,6 +20,7 @@ #import #import +#import #import #import @@ -468,14 +469,13 @@ - (WOResponse *) batchDeleteAction { - NSMutableDictionary *moduleSettings, *threadsCollapsed; + NSMutableDictionary *moduleSettings, *threadsCollapsed, *data; NSString *currentMailbox, *currentAccount, *keyForMsgUIDs; NSMutableArray *mailboxThreadsCollapsed; SOGoMailAccount *account; SOGoUserSettings *us; WOResponse *response; SOGoMailFolder *co; - NSDictionary *data; WORequest *request; id uids, quota; @@ -494,18 +494,16 @@ response = (WOResponse *) [co deleteUIDs: uids useTrashFolder: &withTrash inContext: context]; if (!response) { + data = [NSMutableDictionary dictionary]; if (!withTrash) { // When not using a trash folder, return the quota account = [co mailAccountFolder]; if ((quota = [account getInboxQuota])) { - data = [NSDictionary dictionaryWithObjectsAndKeys: quota, @"quotas", nil]; - response = [self responseWithStatus: 200 - andString: [data jsonRepresentation]]; + [data setObject: quota + forKey: @"quotas"]; } - else - response = [self responseWithStatus: 200]; } else { @@ -519,15 +517,18 @@ if (threadsCollapsed) { - if ((mailboxThreadsCollapsed = [threadsCollapsed objectForKey:keyForMsgUIDs])) + if ((mailboxThreadsCollapsed = [threadsCollapsed objectForKey: keyForMsgUIDs])) { for (i = 0; i < [uids count]; i++) - [mailboxThreadsCollapsed removeObject:[uids objectAtIndex:i]]; + [mailboxThreadsCollapsed removeObject: [uids objectAtIndex:i]]; [us synchronize]; } } - response = [self responseWith204]; } + [data setObject: [NSNumber numberWithUnsignedInt: [co unseenCount]] + forKey: @"unseenCount"]; + response = [self responseWithStatus: 200 + andString: [data jsonRepresentation]]; } } else @@ -681,7 +682,9 @@ [us synchronize]; } } - response = [self responseWith204]; + data = [NSDictionary dictionaryWithObject: [NSNumber numberWithUnsignedInt: [co unseenCount]] + forKey: @"unseenCount"]; + response = [self responseWithStatus: 200 andJSONRepresentation: data]; } else { diff --git a/UI/MailerUI/UIxMailListActions.m b/UI/MailerUI/UIxMailListActions.m index 275649f8d..0779fd922 100644 --- a/UI/MailerUI/UIxMailListActions.m +++ b/UI/MailerUI/UIxMailListActions.m @@ -229,7 +229,6 @@ if (![subject length]) subject = @""; - // NSLog(@"*** subject = |%@|", subject); return subject; } @@ -848,6 +847,7 @@ deletedUids, @"deleted", headers, @"headers", newSyncToken, @"syncToken", + [NSNumber numberWithUnsignedInt: [folder unseenCount]], @"unseenCount", nil]; response = [self responseWithStatus: 200 andJSONRepresentation: data]; } diff --git a/UI/WebServerResources/js/Mailer/Account.service.js b/UI/WebServerResources/js/Mailer/Account.service.js index babdfd2f3..c9c4bd957 100644 --- a/UI/WebServerResources/js/Mailer/Account.service.js +++ b/UI/WebServerResources/js/Mailer/Account.service.js @@ -102,6 +102,61 @@ return collection; }; + /** + * @memberof Account + * @desc Refresh the unseen count for all required mailboxes. + * Starts a timer if user choose to automatically refresh folders. + * @param {array} [string] - the paths of the folders + */ + Account.refreshUnseenCount = function(folders) { + var unseenCountFolders, + fetchAllUnseenCountFolders = (Account.$Preferences.defaults.SOGoMailFetchAllUnseenCountFolders === 1), + refreshViewCheck = Account.$Preferences.defaults.SOGoRefreshViewCheck; + + if (fetchAllUnseenCountFolders) + unseenCountFolders = []; + else if (folders) + unseenCountFolders = folders; + else + throw Error('SOGoMailFetchAllUnseenCountFolders is disabled and no folders list provided'); + + _.forEach(Account.$accounts, function(account) { + if (fetchAllUnseenCountFolders) { + // Include all mailboxes + _.forEach(account.$$flattenMailboxes, function(mailbox) { + unseenCountFolders.push(mailbox.id); + }); + } + else { + // Always include the INBOX + if (!_.includes(unseenCountFolders, account.id + '/folderINBOX')) + unseenCountFolders.push(account.id + '/folderINBOX'); + + _.forEach(account.$$flattenMailboxes, function(mailbox) { + if (angular.isDefined(mailbox.unseenCount) && + !_.includes(unseenCountFolders, mailbox.id)) + unseenCountFolders.push(mailbox.id); + }); + } + }); + + Account.$$resource.post('', 'unseenCount', {mailboxes: unseenCountFolders}).then(function(data) { + _.forEach(Account.$accounts, function(account) { + _.forEach(account.$$flattenMailboxes, function(mailbox) { + if (data[mailbox.id]) { + mailbox.unseenCount = data[mailbox.id]; + } + }); + }); + }); + + if (refreshViewCheck && refreshViewCheck != 'manually') { + if (Account.$refreshUnseenCount) + Account.$timeout.cancel(Account.$refreshUnseenCount); + Account.$refreshUnseenCount = Account.$timeout(angular.bind(this, Account.refreshUnseenCount, folders), refreshViewCheck.timeInterval()*1000); + } + }; + /** * @function getLength * @memberof Account.prototype diff --git a/UI/WebServerResources/js/Mailer/Mailbox.service.js b/UI/WebServerResources/js/Mailer/Mailbox.service.js index 36a01699f..1ca1925ef 100644 --- a/UI/WebServerResources/js/Mailer/Mailbox.service.js +++ b/UI/WebServerResources/js/Mailer/Mailbox.service.js @@ -42,7 +42,6 @@ $Preferences: Preferences, $query: { sort: 'arrival', asc: 0 }, // The default sort must match [UIxMailListActions defaultSortKey] selectedFolder: null, - $selectedMessages: [], $refreshTimeout: null, $virtualMode: false, $virtualPath: false, @@ -167,6 +166,7 @@ this.$messages = []; this.uidsMap = {}; this.$visibleMessages = this.$messages; + this.$selectedMessages = []; } angular.extend(this, data); if (this.path) { @@ -738,15 +738,10 @@ * @memberof Mailbox.prototype * @desc Delete multiple messages from Mailbox object. * @param {string[]} uids - the messages uids - * @param {object[]} messages - the Message instances * @return the index of the first deleted message */ - Mailbox.prototype.$_deleteMessages = function(uids, messages) { - var _this = this, selectedUIDs, _$messages, unseen, firstIndex = this.$messages.length; - - // Decrement the unseen count - unseen = _.filter(messages, function(message, i) { return !message.isread; }); - this.unseenCount -= unseen.length; + Mailbox.prototype.$_deleteMessages = function(uids) { + var _this = this, firstIndex = this.$messages.length; // Remove messages from $messages and uidsMap _.forEachRight(this.$messages, function(message, index) { @@ -767,6 +762,10 @@ } }); + if (this.threaded) { + this.updateVisibleMessages(); + } + // Return the index of the first deleted message return firstIndex; }; @@ -787,19 +786,21 @@ // Recursive function to synchronously delete batch of messages function _deleteMessages(start, end) { var currentUids = uids.slice(start, end), - currentMessages = messages.slice(start, end), data = { uids: currentUids }; if (options) angular.extend(data, options); return Mailbox.$$resource.post(_this.id, 'batchDelete', data).then(function(data) { + if (data.unseenCount) { + _this.unseenCount = data.unseenCount; + } if (end < uids.length) { - _this.$_deleteMessages(currentUids, currentMessages); + _this.$_deleteMessages(currentUids); return _deleteMessages(end, Math.min(end + batchSize, uids.length)); } else { // Last API call; update inbox quota if (data.quotas) _this.$account.updateQuota(data.quotas); - return _this.$_deleteMessages(currentUids, currentMessages); + return _this.$_deleteMessages(currentUids); } }); } @@ -853,9 +854,12 @@ uids = _.map(messages, 'uid'); return Mailbox.$$resource.post(this.id, 'moveMessages', {uids: uids, folder: folder}) - .then(function() { + .then(function(data) { + if (data.unseenCount) { + _this.unseenCount = data.unseenCount; + } _this.$selectedMessages = []; // reset selection - return _this.$_deleteMessages(uids, messages); + return _this.$_deleteMessages(uids); }); }; @@ -984,17 +988,14 @@ _this.$syncToken = data.syncToken; if (data.deleted) { - var deletedMessages = []; _.forEachRight(data.deleted, function(uid, i) { var j = _this.uidsMap[uid.toString()]; - if (j >= 0 && _this.$messages[j]) - deletedMessages.push(_this.$messages[j]); - else + if (j < 0 || !_this.$messages[j]) // Unkown message data.deleted.splice(i, 1); }); - if (deletedMessages.length) - _this.$_deleteMessages(data.deleted, deletedMessages); + if (data.deleted.length) + _this.$_deleteMessages(data.deleted); } if (data.changed) { var i = 0, j; @@ -1013,8 +1014,14 @@ msgObject = _this.$messages[j]; _this.uidsMap[msgObject.uid] += i; } + if (_this.threaded) { + _this.updateVisibleMessages(); + } } } + if (data.unseenCount) { + _this.unseenCount = data.unseenCount; + } if (data.uids) { // Initialization phase, we received complete list of UIDs @@ -1083,10 +1090,6 @@ }); } - if (_this.threaded) { - _this.updateVisibleMessages(); - } - Mailbox.$log.debug('mailbox ' + _this.id + ' ready'); _this.$isLoading = false; deferred.resolve(_this.$messages); diff --git a/UI/WebServerResources/js/Mailer/MailboxController.js b/UI/WebServerResources/js/Mailer/MailboxController.js index 785b3ff04..68b42cbcd 100644 --- a/UI/WebServerResources/js/Mailer/MailboxController.js +++ b/UI/WebServerResources/js/Mailer/MailboxController.js @@ -397,12 +397,6 @@ $state.go('mail.account.mailbox'); } } - else { - $timeout(function() { - console.warn('go to mailbox'); - $state.go('mail.account.mailbox'); - }); - } } this.confirmDeleteSelectedMessages = function($event) { diff --git a/UI/WebServerResources/js/Mailer/MailboxesController.js b/UI/WebServerResources/js/Mailer/MailboxesController.js index d312513cb..dc934252a 100644 --- a/UI/WebServerResources/js/Mailer/MailboxesController.js +++ b/UI/WebServerResources/js/Mailer/MailboxesController.js @@ -34,7 +34,7 @@ this.showSubscribedOnly = Preferences.defaults.SOGoMailShowSubscribedFoldersOnly; - this.refreshUnseenCount(); + Account.refreshUnseenCount($window.unseenCountFolders); _registerHotkeys(hotkeys); @@ -270,49 +270,6 @@ } }; // delegate - this.refreshUnseenCount = function() { - var unseenCountFolders, refreshViewCheck; - - if (Preferences.defaults.SOGoMailFetchAllUnseenCountFolders === 1) - unseenCountFolders = []; - else - unseenCountFolders = $window.unseenCountFolders; - - _.forEach(vm.accounts, function(account) { - if (Preferences.defaults.SOGoMailFetchAllUnseenCountFolders === 1) { - // Include all mailboxes - _.forEach(account.$$flattenMailboxes, function(mailbox) { - unseenCountFolders.push(mailbox.id); - }); - } - else { - // Always include the INBOX - if (!_.includes(unseenCountFolders, account.id + '/folderINBOX')) - unseenCountFolders.push(account.id + '/folderINBOX'); - - _.forEach(account.$$flattenMailboxes, function(mailbox) { - if (angular.isDefined(mailbox.unseenCount) && - !_.includes(unseenCountFolders, mailbox.id)) - unseenCountFolders.push(mailbox.id); - }); - } - }); - - Account.$$resource.post('', 'unseenCount', {mailboxes: unseenCountFolders}).then(function(data) { - _.forEach(vm.accounts, function(account) { - _.forEach(account.$$flattenMailboxes, function(mailbox) { - if (data[mailbox.id]) { - mailbox.unseenCount = data[mailbox.id]; - } - }); - }); - }); - - refreshViewCheck = Preferences.defaults.SOGoRefreshViewCheck; - if (refreshViewCheck && refreshViewCheck != 'manually') - $timeout(vm.refreshUnseenCount, refreshViewCheck.timeInterval()*1000); - }; - this.isDroppableFolder = function(srcFolder, dstFolder) { return (dstFolder.id != srcFolder.id) && !dstFolder.isNoSelect(); };