diff --git a/dev/Boots/RainLoopApp.js b/dev/Boots/RainLoopApp.js index f4ceede34..35c744ed9 100644 --- a/dev/Boots/RainLoopApp.js +++ b/dev/Boots/RainLoopApp.js @@ -267,6 +267,7 @@ RainLoopApp.prototype.folderInformation = function (sFolder, aList) if (oData && oData.Result && oData.Result.Hash && oData.Result.Folder) { var + iUtc = moment().unix(), sHash = RL.cache().getFolderHash(oData.Result.Folder), oFolder = RL.cache().getFolderFromCacheList(oData.Result.Folder), bCheck = false, @@ -278,6 +279,8 @@ RainLoopApp.prototype.folderInformation = function (sFolder, aList) if (oFolder) { + oFolder.interval = iUtc; + if (oData.Result.Hash) { RL.cache().setFolderHash(oData.Result.Folder, oData.Result.Hash); @@ -354,6 +357,94 @@ RainLoopApp.prototype.folderInformation = function (sFolder, aList) } }; +/** + * @param {boolean=} bBoot = false + */ +RainLoopApp.prototype.folderInformationMultiply = function (bBoot) +{ + bBoot = Utils.isUnd(bBoot) ? false : !!bBoot; + + var + iUtc = moment().unix(), + aFolders = RL.data().getNextFolderNames(bBoot) + ; + + if (Utils.isNonEmptyArray(aFolders)) + { + this.remote().folderInformationMultiply(function (sResult, oData) { + if (Enums.StorageResultType.Success === sResult) + { + if (oData && oData.Result && oData.Result.List && Utils.isNonEmptyArray(oData.Result.List)) + { + _.each(oData.Result.List, function (oItem) { + + var + aList = [], + sHash = RL.cache().getFolderHash(oItem.Folder), + oFolder = RL.cache().getFolderFromCacheList(oItem.Folder), + bUnreadCountChange = false + ; + + if (oFolder) + { + oFolder.interval = iUtc; + + if (oItem.Hash) + { + RL.cache().setFolderHash(oItem.Folder, oItem.Hash); + } + + if (Utils.isNormal(oItem.MessageCount)) + { + oFolder.messageCountAll(oItem.MessageCount); + } + + if (Utils.isNormal(oItem.MessageUnseenCount)) + { + if (Utils.pInt(oFolder.messageCountUnread()) !== Utils.pInt(oItem.MessageUnseenCount)) + { + bUnreadCountChange = true; + } + + oFolder.messageCountUnread(oItem.MessageUnseenCount); + } + + if (bUnreadCountChange) + { + RL.cache().clearMessageFlagsFromCacheByFolder(oFolder.fullNameRaw); + } + + if (oItem.Hash !== sHash || '' === sHash) + { + if (oFolder.fullNameRaw === RL.data().currentFolderFullNameRaw()) + { + RL.reloadMessageList(); + } + } + else if (bUnreadCountChange) + { + if (oFolder.fullNameRaw === RL.data().currentFolderFullNameRaw()) + { + aList = RL.data().messageList(); + if (Utils.isNonEmptyArray(aList)) + { + RL.folderInformation(oFolder.fullNameRaw, aList); + } + } + } + } + }); + + if (bBoot) + { + RL.folderInformationMultiply(true); + } + } + } + }, aFolders); + } +}; + RainLoopApp.prototype.setMessageSeen = function (oMessage) { if (oMessage.unseen()) @@ -702,6 +793,30 @@ RainLoopApp.prototype.bootstart = function () RL.socialUsers(true); } + RL.sub('interval.2m', function () { + RL.folderInformation('INBOX'); + }); + + RL.sub('interval.2m', function () { + var sF = RL.data().currentFolderFullNameRaw(); + if ('INBOX' !== sF) + { + RL.folderInformation(sF); + } + }); + + RL.sub('interval.3m', function () { + RL.folderInformationMultiply(); + }); + + RL.sub('interval.5m', function () { + RL.quota(); + }); + + _.delay(function () { + RL.folderInformationMultiply(true); + }, 500); + _.delay(function () { RL.emailsPicsHashes(); @@ -712,15 +827,9 @@ RainLoopApp.prototype.bootstart = function () RL.cache().setServicesData(oData.Result); } }); - }, 1000); - RL.sub('interval.5m', function () { - RL.quota(); - }); + }, 2000); - RL.sub('interval.2m', function () { - RL.folderInformation('INBOX'); - }); Plugins.runHook('rl-start-user-screens'); } diff --git a/dev/Models/EmailModel.js b/dev/Models/EmailModel.js index e2815ba7a..b502cc267 100644 --- a/dev/Models/EmailModel.js +++ b/dev/Models/EmailModel.js @@ -199,64 +199,6 @@ EmailModel.prototype.toLine = function (bFriendlyView, bWrapWithLink, bEncodeHtm return sResult; }; -/** - * @return {string} - */ -EmailModel.prototype.select2Result = function () -{ - var - sResult = '', - sImg = RL.cache().getUserPic(this.email) - ; - - if ('' !== sImg) - { - sResult += ''; - } - else - { - sResult += ''; - } - - if (Enums.EmailType.Facebook === this.type()) - { - sResult += '' + (0 < this.name.length ? this.name : this.email); - sResult += ''; - } - else - { - sResult += '' + (0 < this.name.length ? this.email + ' (' + this.name + ')' : this.email); - } - - return sResult + ''; -}; - -/** - * @param {Object} oContainer - * @return {string|null} - */ -EmailModel.prototype.select2Selection = function (oContainer) -{ - var sResult = ''; - if (Enums.EmailType.Facebook === this.type()) - { - sResult = 0 < this.name.length ? this.name : this.email; - if ('' !== sResult) - { - $('').text(sResult).appendTo(oContainer); - oContainer.append(''); - return null; - } - } - else - { - sResult = 0 < this.name.length ? this.name + ' (' + this.email + ')' : this.email; - } - - return sResult; -}; - - /** * @param {string} $sEmailAddress * @return {boolean} diff --git a/dev/Models/FolderModel.js b/dev/Models/FolderModel.js index d9a9f6b4b..1b66d20b8 100644 --- a/dev/Models/FolderModel.js +++ b/dev/Models/FolderModel.js @@ -20,6 +20,8 @@ function FolderModel() this.isGmailFolder = false; this.isUnpaddigFolder = false; + this.interval = 0; + this.type = ko.observable(Enums.FolderType.User); this.selected = ko.observable(false); @@ -143,10 +145,21 @@ FolderModel.prototype.initComputed = function () RL.data().foldersInboxUnreadCount(iUnread); } -// return 0 < iUnread ? '' + iUnread : ''; -// return 0 < iUnread && 'INBOX' === this.fullNameRaw ? '' + iUnread : ''; - return 0 < iUnread && (Enums.FolderType.Inbox === iType || Enums.FolderType.Spam === iType) ? '' + iUnread : - (0 < iCount && Enums.FolderType.Draft === iType ? '' + iCount : ''); + if (0 < iCount) + { + if (Enums.FolderType.Draft === iType) + { + return '' + iCount; + } + else if (0 < iUnread && Enums.FolderType.Trash !== iType && Enums.FolderType.SentItems !== iType) + { + return '' + iUnread; + } + } + + return ''; +// return 0 < iUnread && (Enums.FolderType.Inbox === iType || Enums.FolderType.Spam === iType) ? '' + iUnread : +// (0 < iCount && Enums.FolderType.Draft === iType ? '' + iCount : ''); }, this); this.canBeDeleted = ko.computed(function () { @@ -261,6 +274,7 @@ FolderModel.prototype.fullNameHash = ''; FolderModel.prototype.delimiter = ''; FolderModel.prototype.namespace = ''; FolderModel.prototype.deep = 0; +FolderModel.prototype.interval = 0; FolderModel.prototype.isNamespaceFolder = false; FolderModel.prototype.isGmailFolder = false; diff --git a/dev/Screens/MailBox.js b/dev/Screens/MailBox.js index 0aabbacf0..f008f8b1d 100644 --- a/dev/Screens/MailBox.js +++ b/dev/Screens/MailBox.js @@ -90,22 +90,6 @@ MailBoxScreen.prototype.onStart = function () } }, 1000); - _.delay(function () { - var sFolder = RL.data().spamFolder(); - if (sFolder !== oData.currentFolderFullNameRaw() && '' !== sFolder) - { - RL.folderInformation(sFolder); - } - }, 1500); - - _.delay(function () { - var sFolder = RL.data().draftFolder(); - if (sFolder !== oData.currentFolderFullNameRaw() && '' !== sFolder) - { - RL.folderInformation(sFolder); - } - }, 2000); - _.delay(function () { RL.quota(); }, 5000); diff --git a/dev/Storages/WebMailAjaxRemote.js b/dev/Storages/WebMailAjaxRemote.js index 5b76513cb..af18e58d7 100644 --- a/dev/Storages/WebMailAjaxRemote.js +++ b/dev/Storages/WebMailAjaxRemote.js @@ -269,6 +269,17 @@ WebMailAjaxRemoteStorage.prototype.folderInformation = function (fCallback, sFol } }; +/** + * @param {?Function} fCallback + * @param {Array} aFolders + */ +WebMailAjaxRemoteStorage.prototype.folderInformationMultiply = function (fCallback, aFolders) +{ + this.defaultRequest(fCallback, 'FolderInformationMultiply', { + 'Folders': aFolders + }); +}; + /** * @param {?Function} fCallback */ diff --git a/dev/Storages/WebMailData.js b/dev/Storages/WebMailData.js index 87fa0ef0d..3e04a4c62 100644 --- a/dev/Storages/WebMailData.js +++ b/dev/Storages/WebMailData.js @@ -650,6 +650,67 @@ WebMailDataStorage.prototype.hideMessageBodies = function () } }; +/** + * @param {boolean=} bBoot = false + * @returns {Array} + */ +WebMailDataStorage.prototype.getNextFolderNames = function (bBoot) +{ + bBoot = Utils.isUnd(bBoot) ? false : !!bBoot; + + var + aResult = [], + iLimit = 10, + iUtc = moment().unix(), + iTimeout = iUtc - 60 * 5, + aTimeouts = [], + fSearchFunction = function (aList) { + _.each(aList, function (oFolder) { + if (oFolder && 'INBOX' !== oFolder.fullNameRaw && + oFolder.selectable && oFolder.existen && + iTimeout > oFolder.interval && + (!bBoot || oFolder.subScribed())) + { + aTimeouts.push([oFolder.interval, oFolder.fullNameRaw]); + } + + if (oFolder && 0 < oFolder.subFolders().length) + { + fSearchFunction(oFolder.subFolders()); + } + }); + } + ; + + fSearchFunction(this.folderList()); + + aTimeouts.sort(function(a, b) { + if (a[0] < b[0]) + { + return -1; + } + else if (a[0] > b[0]) + { + return 1; + } + + return 0; + }); + + _.find(aTimeouts, function (aItem) { + var oFolder = RL.cache().getFolderFromCacheList(aItem[1]); + if (oFolder) + { + oFolder.interval = iUtc; + aResult.push(aItem[1]); + } + + return iLimit <= aResult.length; + }); + + return _.uniq(aResult); +}; + WebMailDataStorage.prototype.setMessage = function (oData, bCached) { var @@ -777,6 +838,7 @@ WebMailDataStorage.prototype.setMessageList = function (oData, bCached) iCount = 0, iOffset = 0, aList = [], + iUtc = moment().unix(), aStaticList = oRainLoopData.staticMessageList, oJsonMessage = null, oMessage = null, @@ -798,6 +860,8 @@ WebMailDataStorage.prototype.setMessageList = function (oData, bCached) if (oFolder && !bCached) { + oFolder.interval = iUtc; + RL.cache().setFolderHash(oData.Result.Folder, oData.Result.FolderHash); if (Utils.isNormal(oData.Result.MessageCount)) diff --git a/package.json b/package.json index efbaed377..546103430 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "RainLoop", "title": "RainLoop Webmail", "version": "1.5.1", - "release": "547", + "release": "549", "description": "Simple, modern & fast web-based email client", "homepage": "http://rainloop.net", "main": "Gruntfile.js", diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php index 06e26e909..2a0de5cc3 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php @@ -3417,7 +3417,7 @@ class Actions $aFlagsFilteredUids = array(); if (0 < strlen($sFlagsUids)) { - $aFlagsUids = explode(',', (string) $this->GetActionParam('FlagsUids', '')); + $aFlagsUids = explode(',', $sFlagsUids); $aFlagsFilteredUids = array_filter($aFlagsUids, function (&$sUid) { $sUid = (int) trim($sUid); return 0 < (int) trim($sUid); @@ -3431,15 +3431,18 @@ class Actions try { $aInboxInformation = $this->MailClient()->FolderInformation($sFolder, $sPrevUidNext, $aFlagsFilteredUids); - foreach ($aInboxInformation['Flags'] as $iUid => $aFlags) + if (\is_array($aInboxInformation) && isset($aInboxInformation['Flags']) && \is_array($aInboxInformation['Flags'])) { - $aLowerFlags = array_map('strtolower', $aFlags); - $aInboxInformation['Flags'][$iUid] = array( - 'IsSeen' => in_array('\\seen', $aLowerFlags), - 'IsFlagged' => in_array('\\flagged', $aLowerFlags), - 'IsAnswered' => in_array('\\answered', $aLowerFlags), - 'IsForwarded' => 0 < strlen($sForwardedFlag) && in_array(strtolower($sForwardedFlag), $aLowerFlags) - ); + foreach ($aInboxInformation['Flags'] as $iUid => $aFlags) + { + $aLowerFlags = array_map('strtolower', $aFlags); + $aInboxInformation['Flags'][$iUid] = array( + 'IsSeen' => in_array('\\seen', $aLowerFlags), + 'IsFlagged' => in_array('\\flagged', $aLowerFlags), + 'IsAnswered' => in_array('\\answered', $aLowerFlags), + 'IsForwarded' => 0 < strlen($sForwardedFlag) && in_array(strtolower($sForwardedFlag), $aLowerFlags) + ); + } } } catch (\Exception $oException) @@ -3455,6 +3458,47 @@ class Actions return $this->DefaultResponse(__FUNCTION__, $aInboxInformation); } + /** + * @return array + * + * @throws \MailSo\Base\Exceptions\Exception + */ + public function DoFolderInformationMultiply() + { + $aResult = array( + 'List' => array(), + 'Version' => APP_VERSION + ); + + $aFolders = $this->GetActionParam('Folders', null); + if (\is_array($aFolders)) + { + $this->initMailClientConnection(); + + $aFolders = \array_unique($aFolders); + foreach ($aFolders as $sFolder) + { + if (0 < \strlen(\trim($sFolder)) && 'INBOX' !== \strtoupper($sFolder)) + { + try + { + $aInboxInformation = $this->MailClient()->FolderInformation($sFolder); + if (\is_array($aInboxInformation) && isset($aInboxInformation['Folder'])) + { + $aResult['List'][] = $aInboxInformation; + } + } + catch (\Exception $oException) + { + $this->Logger()->WriteException($oException); + } + } + } + } + + return $this->DefaultResponse(__FUNCTION__, $aResult); + } + /** * @return array * diff --git a/rainloop/v/0.0.0/app/templates/Views/AdminSettingsLicensing.html b/rainloop/v/0.0.0/app/templates/Views/AdminSettingsLicensing.html index 01f33b81f..721848042 100644 --- a/rainloop/v/0.0.0/app/templates/Views/AdminSettingsLicensing.html +++ b/rainloop/v/0.0.0/app/templates/Views/AdminSettingsLicensing.html @@ -60,11 +60,18 @@ diff --git a/rainloop/v/0.0.0/app/templates/Views/Login.html b/rainloop/v/0.0.0/app/templates/Views/Login.html index 826aba925..2807e4245 100644 --- a/rainloop/v/0.0.0/app/templates/Views/Login.html +++ b/rainloop/v/0.0.0/app/templates/Views/Login.html @@ -56,7 +56,7 @@ {{INCLUDE/MenuDropdownTop/PLACE}}
  • - +    diff --git a/rainloop/v/0.0.0/app/templates/Views/MailFolderListItem.html b/rainloop/v/0.0.0/app/templates/Views/MailFolderListItem.html index a93867271..33724b791 100644 --- a/rainloop/v/0.0.0/app/templates/Views/MailFolderListItem.html +++ b/rainloop/v/0.0.0/app/templates/Views/MailFolderListItem.html @@ -1,10 +1,11 @@ -
    - - - - -
    + \ No newline at end of file diff --git a/rainloop/v/0.0.0/app/templates/Views/PopupsActivate.html b/rainloop/v/0.0.0/app/templates/Views/PopupsActivate.html index 9aa8aeb07..1ed8b1b93 100644 --- a/rainloop/v/0.0.0/app/templates/Views/PopupsActivate.html +++ b/rainloop/v/0.0.0/app/templates/Views/PopupsActivate.html @@ -42,11 +42,6 @@