From d4c4f84c13692d7eb6a9ff1c2e96054ba8786748 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Thu, 29 Dec 2022 13:40:46 +0100 Subject: [PATCH] https://github.com/the-djmaze/snappymail/issues/796#issuecomment-1367247159 --- dev/Common/Folders.js | 2 +- dev/Model/MessageCollection.js | 15 +++-- dev/Remote/User/Fetch.js | 16 +++--- dev/Stores/User/Messagelist.js | 28 +++++----- dev/View/User/MailBox/MessageList.js | 8 +-- .../app/libraries/MailSo/Mail/MailClient.php | 56 ++++++++++--------- .../MailSo/Mail/MessageCollection.php | 17 +++--- .../libraries/RainLoop/Actions/Messages.php | 32 +++++------ .../templates/Views/User/MailMessageList.html | 4 +- 9 files changed, 94 insertions(+), 84 deletions(-) diff --git a/dev/Common/Folders.js b/dev/Common/Folders.js index f0a589836..0d3d15720 100644 --- a/dev/Common/Folders.js +++ b/dev/Common/Folders.js @@ -153,7 +153,7 @@ folderInformation = (folder, list) => { MessagelistUserStore.reloadFlagsAndCachedMessage(); } - MessagelistUserStore.notifyNewMessages(folderFromCache.fullName, result.NewMessages); + MessagelistUserStore.notifyNewMessages(folderFromCache.fullName, result.newMessages); if (!oldHash || unreadCountChange || result.Hash !== oldHash) { if (folderFromCache.fullName === FolderUserStore.currentFolderFullName()) { diff --git a/dev/Model/MessageCollection.js b/dev/Model/MessageCollection.js index 4e5ebc1a8..55c6d2d92 100644 --- a/dev/Model/MessageCollection.js +++ b/dev/Model/MessageCollection.js @@ -14,16 +14,15 @@ export class MessageCollectionModel extends AbstractCollectionModel super(); this.Filtered this.Folder - this.FolderHash - this.FolderInfo + this.folderHash + this.folderInfo this.totalEmails this.unreadEmails - this.UidNext - this.ThreadUid - this.NewMessages - this.Offset - this.Limit - this.Search + this.threadUid + this.newMessages + this.offset + this.limit + this.search } */ diff --git a/dev/Remote/User/Fetch.js b/dev/Remote/User/Fetch.js index 4eab1b392..aca3ddf26 100644 --- a/dev/Remote/User/Fetch.js +++ b/dev/Remote/User/Fetch.js @@ -27,23 +27,23 @@ class RemoteUserFetch extends AbstractFetchRemote { folderHash = folder?.hash || ''; params = Object.assign({ - Offset: 0, - Limit: SettingsUserStore.messagesPerPage(), - Search: '', - UidNext: folder?.uidNext || 0, // Used to check for new messages - Sort: FolderUserStore.sortMode(), + offset: 0, + limit: SettingsUserStore.messagesPerPage(), + search: '', + uidNext: folder?.uidNext || 0, // Used to check for new messages + sort: FolderUserStore.sortMode(), Hash: folderHash + SettingsGet('AccountHash') }, params); params.Folder = sFolderFullName; if (AppUserStore.threadsAllowed() && SettingsUserStore.useThreads()) { - params.UseThreads = 1; + params.useThreads = 1; } else { - params.ThreadUid = 0; + params.threadUid = 0; } let sGetAdd = ''; - if (folderHash && (!params.Search || !params.Search.includes('is:'))) { + if (folderHash && (!params.search || !params.search.includes('is:'))) { sGetAdd = 'MessageList/' + SUB_QUERY_PREFIX + '/' + diff --git a/dev/Stores/User/Messagelist.js b/dev/Stores/User/Messagelist.js index 6bf341a9b..64f0f94a1 100644 --- a/dev/Stores/User/Messagelist.js +++ b/dev/Stores/User/Messagelist.js @@ -42,6 +42,7 @@ export const MessagelistUserStore = ko.observableArray().extend({ debounce: 0 }) addObservablesTo(MessagelistUserStore, { count: 0, listSearch: '', + listLimited: 0, threadUid: 0, page: 1, pageBeforeThread: 1, @@ -208,12 +209,12 @@ MessagelistUserStore.reload = (bDropPagePosition = false, bDropCurrentFolderCach const folder = getFolderFromCacheList(collection.Folder), - folderInfo = collection.FolderInfo; + folderInfo = collection.folderInfo; if (folder && !bCached) { // folder.revivePropertiesFromJson(result); folder.expires = Date.now(); folder.uidNext = folderInfo.UidNext; - folder.hash = collection.FolderHash; + folder.hash = collection.folderHash; if (null != folderInfo.totalEmails) { folder.totalEmails(folderInfo.totalEmails); @@ -242,21 +243,22 @@ MessagelistUserStore.reload = (bDropPagePosition = false, bDropCurrentFolderCach }); folder.permanentFlags(flags); - MessagelistUserStore.notifyNewMessages(folder.fullName, collection.NewMessages); + MessagelistUserStore.notifyNewMessages(folder.fullName, collection.newMessages); } MessagelistUserStore.count(collection.totalEmails); - MessagelistUserStore.listSearch(pString(collection.Search)); - MessagelistUserStore.page(Math.ceil(collection.Offset / SettingsUserStore.messagesPerPage() + 1)); - MessagelistUserStore.threadUid(collection.ThreadUid); + MessagelistUserStore.listSearch(pString(collection.search)); + MessagelistUserStore.listLimited(!!collection.limited); + MessagelistUserStore.page(Math.ceil(collection.offset / SettingsUserStore.messagesPerPage() + 1)); + MessagelistUserStore.threadUid(collection.threadUid); MessagelistUserStore.endHash( collection.Folder + - '|' + collection.Search + + '|' + collection.search + '|' + MessagelistUserStore.threadUid() + '|' + MessagelistUserStore.page() ); - MessagelistUserStore.endThreadUid(collection.ThreadUid); + MessagelistUserStore.endThreadUid(collection.threadUid); const message = MessageUserStore.message(); if (message && collection.Folder !== message.folder) { MessageUserStore.message(null); @@ -264,7 +266,7 @@ MessagelistUserStore.reload = (bDropPagePosition = false, bDropCurrentFolderCach disableAutoSelect(true); - if (collection.ThreadUid) { + if (collection.threadUid) { let refs = {}; collection.forEach(msg => { msg.level = 0; @@ -292,10 +294,10 @@ MessagelistUserStore.reload = (bDropPagePosition = false, bDropCurrentFolderCach }, { Folder: FolderUserStore.currentFolderFullName(), - Offset: iOffset, - Limit: SettingsUserStore.messagesPerPage(), - Search: MessagelistUserStore.listSearch(), - ThreadUid: MessagelistUserStore.threadUid() + offset: iOffset, + limit: SettingsUserStore.messagesPerPage(), + search: MessagelistUserStore.listSearch(), + threadUid: MessagelistUserStore.threadUid() } ); }; diff --git a/dev/View/User/MailBox/MessageList.js b/dev/View/User/MailBox/MessageList.js index 04cffae8d..46dbd75cf 100644 --- a/dev/View/User/MailBox/MessageList.js +++ b/dev/View/User/MailBox/MessageList.js @@ -115,10 +115,10 @@ export class MailMessageList extends AbstractViewRight { sortSupported: () => (FolderUserStore.hasCapability('SORT') | FolderUserStore.hasCapability('ESORT')) - && !MessagelistUserStore.threadUid(), + && !(MessagelistUserStore.listLimited() | MessagelistUserStore.threadUid()), messageListSearchDesc: () => { - const value = MessagelistUserStore().Search; + const value = MessagelistUserStore().search; return value ? i18n('MESSAGE_LIST/SEARCH_RESULT_FOR', { SEARCH: value }) : '' }, @@ -150,7 +150,7 @@ export class MailMessageList extends AbstractViewRight { listGrouped: () => { let uid = MessagelistUserStore.threadUid(), sort = FolderUserStore.sortMode() || 'DATE'; - return SettingsUserStore.listGrouped() && sort.includes('DATE') && !uid; + return SettingsUserStore.listGrouped() && (sort.includes('DATE') || sort.includes('FROM')) && !uid; }, timeFormat: () => (FolderUserStore.sortMode() || '').includes('FROM') ? 'SHORT' : 'LT', @@ -159,7 +159,7 @@ export class MailMessageList extends AbstractViewRight { let list = [], current, sort = FolderUserStore.sortMode() || 'DATE'; if (sort.includes('FROM')) { MessagelistUserStore.forEach(msg => { - let email = msg.from[0].email; + let email = msg.from?.[0].email; if (!current || email != current.id) { current = { id: email, diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php b/snappymail/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php index a08e276b8..1298d73bb 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php @@ -381,7 +381,7 @@ class MailClient // 'PermanentFlags' => $oInfo->PermanentFlags, 'Hash' => $oInfo->getHash($this->oImapClient->Hash()), 'MessagesFlags' => $aFlags, - 'NewMessages' => $this->getFolderNextMessageInformation( + 'newMessages' => $this->getFolderNextMessageInformation( $sFolderName, $iPrevUidNext, \intval($oInfo->UIDNEXT) @@ -505,10 +505,20 @@ class MailClient * @throws \MailSo\Imap\Exceptions\* */ private function GetUids(MessageListParams $oParams, string $sSearch, - string $sFolderName, string $sFolderHash, - bool $bUseSortIfSupported = false, string $sSort = '') : array + string $sFolderHash, bool $bUseSortIfSupported = false) : array { $oCacher = $oParams->oCacher; + $sFolderName = $oParams->sFolderName; + + $aResultUids = false; + $bUidsFromCacher = false; + $bUseCacheAfterSearch = $oCacher && $oCacher->IsInited(); + + $sSerializedHash = ''; + $sSerializedLog = ''; + + $bUseSortIfSupported = $bUseSortIfSupported && !\strlen($sSearch) && $this->oImapClient->hasCapability('SORT'); + $sSort = $bUseSortIfSupported ? $oParams->sSort : ''; /* TODO: Validate $sSort ARRIVAL Internal date and time of the message. This differs from the @@ -550,15 +560,6 @@ class MailClient DISPLAYFROM, DISPLAYTO */ - $aResultUids = false; - $bUidsFromCacher = false; - $bUseCacheAfterSearch = $oCacher && $oCacher->IsInited(); - - $sSerializedHash = ''; - $sSerializedLog = ''; - - $bUseSortIfSupported = $bUseSortIfSupported && !\strlen($sSearch) && $this->oImapClient->hasCapability('SORT'); - $sSearchCriterias = \MailSo\Imap\SearchCriterias::fromString($this->oImapClient, $sFolderName, $sSearch, $oParams->bHideDeleted, $bUseCacheAfterSearch); // Disabled for now as there are many cases that change the result $bUseCacheAfterSearch = false; @@ -588,9 +589,17 @@ class MailClient if (!$bUidsFromCacher) { if ($bUseSortIfSupported) { + $aSortTypes = []; + if ($sSort) { + $aSortTypes[] = $sSort; + } + if (false === \strpos($sSort, 'DATE')) { + // Always also sort DATE descending when DATE is not defined + $aSortTypes[] = 'REVERSE DATE'; + } // $this->oImapClient->hasCapability('ESORT') -// $aResultUids = $this->oImapClient->MessageSimpleESort(array($sSort ?: 'REVERSE DATE'), $sSearchCriterias)['ALL']; - $aResultUids = $this->oImapClient->MessageSimpleSort(array($sSort ?: 'REVERSE DATE'), $sSearchCriterias); +// $aResultUids = $this->oImapClient->MessageSimpleESort($aSortTypes, $sSearchCriterias)['ALL']; + $aResultUids = $this->oImapClient->MessageSimpleSort($aSortTypes, $sSearchCriterias); } else { // $this->oImapClient->hasCapability('ESEARCH') // $aResultUids = $this->oImapClient->MessageSimpleESearch($sSearchCriterias, null, true, \MailSo\Base\Utils::IsAscii($sSearchCriterias) ? '' : 'UTF-8') @@ -660,14 +669,14 @@ class MailClient if ($oInfo->MESSAGES) { if (0 < $this->oImapClient->Settings->message_list_limit && $this->oImapClient->Settings->message_list_limit < $oInfo->MESSAGES) { + // Don't use SORT nor THREAD + $oMessageCollection->Limited = true; if ($this->oLogger) { $this->oLogger->Write('List optimization (count: '.$oInfo->MESSAGES. ', limit:'.$this->oImapClient->Settings->message_list_limit.')'); } if (\strlen($sSearch)) { - $aUids = $this->GetUids($oParams, $sSearch, - $oMessageCollection->FolderName, $oMessageCollection->FolderHash); - + $aUids = $this->GetUids($oParams, $sSearch, $oMessageCollection->FolderHash); $oMessageCollection->totalEmails = \count($aUids); if ($oMessageCollection->totalEmails) { $this->MessageListByRequestIndexOrUids( @@ -680,7 +689,8 @@ class MailClient if (1 < $oInfo->MESSAGES) { $end = \max(1, $oInfo->MESSAGES - $oParams->iOffset); $start = \max(1, $end - $oParams->iLimit + 1); - $aRequestIndexes = \range($start, $end); + // Attempt to sort REVERSE DATE + $aRequestIndexes = \range($end, $start); } else { $aRequestIndexes = \array_slice([1], $oParams->iOffset, 1); } @@ -688,7 +698,6 @@ class MailClient } } else { $aUids = []; - $bUseSortIfSupported = $oParams->bUseSortIfSupported && $this->oImapClient->hasCapability('SORT'); if ($bUseThreads) { $aAllThreads = $this->MessageListThreadsMap($oMessageCollection->FolderName, $oMessageCollection->FolderHash, $oParams->oCacher); $oMessageCollection->totalThreads = \count($aAllThreads); @@ -703,8 +712,7 @@ class MailClient } } } else { - $aUids = $this->GetUids($oParams, '', - $oMessageCollection->FolderName, $oMessageCollection->FolderHash, $bUseSortIfSupported, $oParams->sSort); + $aUids = $this->GetUids($oParams, '', $oMessageCollection->FolderHash, $oParams->bUseSortIfSupported); // Remove all threaded UID's except the most recent of each thread $threadedUids = []; foreach ($aAllThreads as $aMap) { @@ -714,13 +722,11 @@ class MailClient $aUids = \array_diff($aUids, $threadedUids); } } else { - $aUids = $this->GetUids($oParams, '', - $oMessageCollection->FolderName, $oMessageCollection->FolderHash, $bUseSortIfSupported, $oParams->sSort); + $aUids = $this->GetUids($oParams, '', $oMessageCollection->FolderHash, $oParams->bUseSortIfSupported); } if ($aUids && \strlen($sSearch)) { - $aSearchedUids = $this->GetUids($oParams, $sSearch, - $oMessageCollection->FolderName, $oMessageCollection->FolderHash); + $aSearchedUids = $this->GetUids($oParams, $sSearch, $oMessageCollection->FolderHash); if ($bUseThreads && !$oParams->iThreadUid) { $matchingThreadUids = []; foreach ($aAllThreads as $aMap) { diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Mail/MessageCollection.php b/snappymail/v/0.0.0/app/libraries/MailSo/Mail/MessageCollection.php index b974653c0..3ffe90be5 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Mail/MessageCollection.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Mail/MessageCollection.php @@ -43,6 +43,8 @@ class MessageCollection extends \MailSo\Base\Collection // public bool $Filtered = false; + public bool $Limited = false; + public function append($oMessage, bool $bToTop = false) : void { assert($oMessage instanceof Message); @@ -61,14 +63,15 @@ class MessageCollection extends \MailSo\Base\Collection 'totalEmails' => $this->totalEmails, 'totalThreads' => $this->totalThreads, 'Folder' => $this->FolderName, - 'FolderHash' => $this->FolderHash, - 'FolderInfo' => $this->FolderInfo, - 'ThreadUid' => $this->ThreadUid, - 'NewMessages' => $this->NewMessages, + 'folderHash' => $this->FolderHash, + 'folderInfo' => $this->FolderInfo, + 'threadUid' => $this->ThreadUid, + 'newMessages' => $this->NewMessages, // 'Filtered' => $this->Filtered, - 'Offset' => $this->Offset, - 'Limit' => $this->Limit, - 'Search' => $this->Search + 'offset' => $this->Offset, + 'limit' => $this->Limit, + 'search' => $this->Search, + 'limited' => $this->Limited )); } } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Messages.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Messages.php index 2e1df47e9..1a10d3714 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Messages.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Messages.php @@ -30,27 +30,27 @@ trait Messages // $oParams->sHash = (string) $aValues['Hash']; $oParams->sFolderName = (string) $aValues['Folder']; - $oParams->iLimit = $aValues['Limit']; - $oParams->iOffset = $aValues['Offset']; - $oParams->sSearch = (string) $aValues['Search']; - $oParams->sSort = (string) $aValues['Sort']; - if (isset($aValues['UidNext'])) { - $oParams->iPrevUidNext = $aValues['UidNext']; + $oParams->iLimit = $aValues['limit']; + $oParams->iOffset = $aValues['offset']; + $oParams->sSearch = (string) $aValues['search']; + $oParams->sSort = (string) $aValues['sort']; + if (isset($aValues['uidNext'])) { + $oParams->iPrevUidNext = $aValues['uidNext']; } - $oParams->bUseThreads = !empty($aValues['UseThreads']); - if ($oParams->bUseThreads && isset($aValues['ThreadUid'])) { - $oParams->iThreadUid = $aValues['ThreadUid']; + $oParams->bUseThreads = !empty($aValues['useThreads']); + if ($oParams->bUseThreads && isset($aValues['threadUid'])) { + $oParams->iThreadUid = $aValues['threadUid']; } } else { $oParams->sFolderName = $this->GetActionParam('Folder', ''); - $oParams->iOffset = $this->GetActionParam('Offset', 0); - $oParams->iLimit = $this->GetActionParam('Limit', 10); - $oParams->sSearch = $this->GetActionParam('Search', ''); - $oParams->sSort = $this->GetActionParam('Sort', ''); - $oParams->iPrevUidNext = $this->GetActionParam('UidNext', 0); - $oParams->bUseThreads = !empty($this->GetActionParam('UseThreads', '0')); + $oParams->iOffset = $this->GetActionParam('offset', 0); + $oParams->iLimit = $this->GetActionParam('limit', 10); + $oParams->sSearch = $this->GetActionParam('search', ''); + $oParams->sSort = $this->GetActionParam('sort', ''); + $oParams->iPrevUidNext = $this->GetActionParam('uidNext', 0); + $oParams->bUseThreads = !empty($this->GetActionParam('useThreads', '0')); if ($oParams->bUseThreads) { - $oParams->iThreadUid = $this->GetActionParam('ThreadUid', ''); + $oParams->iThreadUid = $this->GetActionParam('threadUid', ''); } } diff --git a/snappymail/v/0.0.0/app/templates/Views/User/MailMessageList.html b/snappymail/v/0.0.0/app/templates/Views/User/MailMessageList.html index a212cd53b..57d9fe607 100644 --- a/snappymail/v/0.0.0/app/templates/Views/User/MailMessageList.html +++ b/snappymail/v/0.0.0/app/templates/Views/User/MailMessageList.html @@ -93,10 +93,10 @@