the-djmaze 2022-12-29 13:40:46 +01:00
parent 1cff18218e
commit d4c4f84c13
9 changed files with 94 additions and 84 deletions

View file

@ -153,7 +153,7 @@ folderInformation = (folder, list) => {
MessagelistUserStore.reloadFlagsAndCachedMessage(); MessagelistUserStore.reloadFlagsAndCachedMessage();
} }
MessagelistUserStore.notifyNewMessages(folderFromCache.fullName, result.NewMessages); MessagelistUserStore.notifyNewMessages(folderFromCache.fullName, result.newMessages);
if (!oldHash || unreadCountChange || result.Hash !== oldHash) { if (!oldHash || unreadCountChange || result.Hash !== oldHash) {
if (folderFromCache.fullName === FolderUserStore.currentFolderFullName()) { if (folderFromCache.fullName === FolderUserStore.currentFolderFullName()) {

View file

@ -14,16 +14,15 @@ export class MessageCollectionModel extends AbstractCollectionModel
super(); super();
this.Filtered this.Filtered
this.Folder this.Folder
this.FolderHash this.folderHash
this.FolderInfo this.folderInfo
this.totalEmails this.totalEmails
this.unreadEmails this.unreadEmails
this.UidNext this.threadUid
this.ThreadUid this.newMessages
this.NewMessages this.offset
this.Offset this.limit
this.Limit this.search
this.Search
} }
*/ */

View file

@ -27,23 +27,23 @@ class RemoteUserFetch extends AbstractFetchRemote {
folderHash = folder?.hash || ''; folderHash = folder?.hash || '';
params = Object.assign({ params = Object.assign({
Offset: 0, offset: 0,
Limit: SettingsUserStore.messagesPerPage(), limit: SettingsUserStore.messagesPerPage(),
Search: '', search: '',
UidNext: folder?.uidNext || 0, // Used to check for new messages uidNext: folder?.uidNext || 0, // Used to check for new messages
Sort: FolderUserStore.sortMode(), sort: FolderUserStore.sortMode(),
Hash: folderHash + SettingsGet('AccountHash') Hash: folderHash + SettingsGet('AccountHash')
}, params); }, params);
params.Folder = sFolderFullName; params.Folder = sFolderFullName;
if (AppUserStore.threadsAllowed() && SettingsUserStore.useThreads()) { if (AppUserStore.threadsAllowed() && SettingsUserStore.useThreads()) {
params.UseThreads = 1; params.useThreads = 1;
} else { } else {
params.ThreadUid = 0; params.threadUid = 0;
} }
let sGetAdd = ''; let sGetAdd = '';
if (folderHash && (!params.Search || !params.Search.includes('is:'))) { if (folderHash && (!params.search || !params.search.includes('is:'))) {
sGetAdd = 'MessageList/' + sGetAdd = 'MessageList/' +
SUB_QUERY_PREFIX + SUB_QUERY_PREFIX +
'/' + '/' +

View file

@ -42,6 +42,7 @@ export const MessagelistUserStore = ko.observableArray().extend({ debounce: 0 })
addObservablesTo(MessagelistUserStore, { addObservablesTo(MessagelistUserStore, {
count: 0, count: 0,
listSearch: '', listSearch: '',
listLimited: 0,
threadUid: 0, threadUid: 0,
page: 1, page: 1,
pageBeforeThread: 1, pageBeforeThread: 1,
@ -208,12 +209,12 @@ MessagelistUserStore.reload = (bDropPagePosition = false, bDropCurrentFolderCach
const const
folder = getFolderFromCacheList(collection.Folder), folder = getFolderFromCacheList(collection.Folder),
folderInfo = collection.FolderInfo; folderInfo = collection.folderInfo;
if (folder && !bCached) { if (folder && !bCached) {
// folder.revivePropertiesFromJson(result); // folder.revivePropertiesFromJson(result);
folder.expires = Date.now(); folder.expires = Date.now();
folder.uidNext = folderInfo.UidNext; folder.uidNext = folderInfo.UidNext;
folder.hash = collection.FolderHash; folder.hash = collection.folderHash;
if (null != folderInfo.totalEmails) { if (null != folderInfo.totalEmails) {
folder.totalEmails(folderInfo.totalEmails); folder.totalEmails(folderInfo.totalEmails);
@ -242,21 +243,22 @@ MessagelistUserStore.reload = (bDropPagePosition = false, bDropCurrentFolderCach
}); });
folder.permanentFlags(flags); folder.permanentFlags(flags);
MessagelistUserStore.notifyNewMessages(folder.fullName, collection.NewMessages); MessagelistUserStore.notifyNewMessages(folder.fullName, collection.newMessages);
} }
MessagelistUserStore.count(collection.totalEmails); MessagelistUserStore.count(collection.totalEmails);
MessagelistUserStore.listSearch(pString(collection.Search)); MessagelistUserStore.listSearch(pString(collection.search));
MessagelistUserStore.page(Math.ceil(collection.Offset / SettingsUserStore.messagesPerPage() + 1)); MessagelistUserStore.listLimited(!!collection.limited);
MessagelistUserStore.threadUid(collection.ThreadUid); MessagelistUserStore.page(Math.ceil(collection.offset / SettingsUserStore.messagesPerPage() + 1));
MessagelistUserStore.threadUid(collection.threadUid);
MessagelistUserStore.endHash( MessagelistUserStore.endHash(
collection.Folder + collection.Folder +
'|' + collection.Search + '|' + collection.search +
'|' + MessagelistUserStore.threadUid() + '|' + MessagelistUserStore.threadUid() +
'|' + MessagelistUserStore.page() '|' + MessagelistUserStore.page()
); );
MessagelistUserStore.endThreadUid(collection.ThreadUid); MessagelistUserStore.endThreadUid(collection.threadUid);
const message = MessageUserStore.message(); const message = MessageUserStore.message();
if (message && collection.Folder !== message.folder) { if (message && collection.Folder !== message.folder) {
MessageUserStore.message(null); MessageUserStore.message(null);
@ -264,7 +266,7 @@ MessagelistUserStore.reload = (bDropPagePosition = false, bDropCurrentFolderCach
disableAutoSelect(true); disableAutoSelect(true);
if (collection.ThreadUid) { if (collection.threadUid) {
let refs = {}; let refs = {};
collection.forEach(msg => { collection.forEach(msg => {
msg.level = 0; msg.level = 0;
@ -292,10 +294,10 @@ MessagelistUserStore.reload = (bDropPagePosition = false, bDropCurrentFolderCach
}, },
{ {
Folder: FolderUserStore.currentFolderFullName(), Folder: FolderUserStore.currentFolderFullName(),
Offset: iOffset, offset: iOffset,
Limit: SettingsUserStore.messagesPerPage(), limit: SettingsUserStore.messagesPerPage(),
Search: MessagelistUserStore.listSearch(), search: MessagelistUserStore.listSearch(),
ThreadUid: MessagelistUserStore.threadUid() threadUid: MessagelistUserStore.threadUid()
} }
); );
}; };

View file

@ -115,10 +115,10 @@ export class MailMessageList extends AbstractViewRight {
sortSupported: () => sortSupported: () =>
(FolderUserStore.hasCapability('SORT') | FolderUserStore.hasCapability('ESORT')) (FolderUserStore.hasCapability('SORT') | FolderUserStore.hasCapability('ESORT'))
&& !MessagelistUserStore.threadUid(), && !(MessagelistUserStore.listLimited() | MessagelistUserStore.threadUid()),
messageListSearchDesc: () => { messageListSearchDesc: () => {
const value = MessagelistUserStore().Search; const value = MessagelistUserStore().search;
return value ? i18n('MESSAGE_LIST/SEARCH_RESULT_FOR', { SEARCH: value }) : '' return value ? i18n('MESSAGE_LIST/SEARCH_RESULT_FOR', { SEARCH: value }) : ''
}, },
@ -150,7 +150,7 @@ export class MailMessageList extends AbstractViewRight {
listGrouped: () => { listGrouped: () => {
let uid = MessagelistUserStore.threadUid(), let uid = MessagelistUserStore.threadUid(),
sort = FolderUserStore.sortMode() || 'DATE'; 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', timeFormat: () => (FolderUserStore.sortMode() || '').includes('FROM') ? 'SHORT' : 'LT',
@ -159,7 +159,7 @@ export class MailMessageList extends AbstractViewRight {
let list = [], current, sort = FolderUserStore.sortMode() || 'DATE'; let list = [], current, sort = FolderUserStore.sortMode() || 'DATE';
if (sort.includes('FROM')) { if (sort.includes('FROM')) {
MessagelistUserStore.forEach(msg => { MessagelistUserStore.forEach(msg => {
let email = msg.from[0].email; let email = msg.from?.[0].email;
if (!current || email != current.id) { if (!current || email != current.id) {
current = { current = {
id: email, id: email,

View file

@ -381,7 +381,7 @@ class MailClient
// 'PermanentFlags' => $oInfo->PermanentFlags, // 'PermanentFlags' => $oInfo->PermanentFlags,
'Hash' => $oInfo->getHash($this->oImapClient->Hash()), 'Hash' => $oInfo->getHash($this->oImapClient->Hash()),
'MessagesFlags' => $aFlags, 'MessagesFlags' => $aFlags,
'NewMessages' => $this->getFolderNextMessageInformation( 'newMessages' => $this->getFolderNextMessageInformation(
$sFolderName, $sFolderName,
$iPrevUidNext, $iPrevUidNext,
\intval($oInfo->UIDNEXT) \intval($oInfo->UIDNEXT)
@ -505,10 +505,20 @@ class MailClient
* @throws \MailSo\Imap\Exceptions\* * @throws \MailSo\Imap\Exceptions\*
*/ */
private function GetUids(MessageListParams $oParams, string $sSearch, private function GetUids(MessageListParams $oParams, string $sSearch,
string $sFolderName, string $sFolderHash, string $sFolderHash, bool $bUseSortIfSupported = false) : array
bool $bUseSortIfSupported = false, string $sSort = '') : array
{ {
$oCacher = $oParams->oCacher; $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 /* TODO: Validate $sSort
ARRIVAL ARRIVAL
Internal date and time of the message. This differs from the Internal date and time of the message. This differs from the
@ -550,15 +560,6 @@ class MailClient
DISPLAYFROM, DISPLAYTO 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); $sSearchCriterias = \MailSo\Imap\SearchCriterias::fromString($this->oImapClient, $sFolderName, $sSearch, $oParams->bHideDeleted, $bUseCacheAfterSearch);
// Disabled for now as there are many cases that change the result // Disabled for now as there are many cases that change the result
$bUseCacheAfterSearch = false; $bUseCacheAfterSearch = false;
@ -588,9 +589,17 @@ class MailClient
if (!$bUidsFromCacher) { if (!$bUidsFromCacher) {
if ($bUseSortIfSupported) { 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') // $this->oImapClient->hasCapability('ESORT')
// $aResultUids = $this->oImapClient->MessageSimpleESort(array($sSort ?: 'REVERSE DATE'), $sSearchCriterias)['ALL']; // $aResultUids = $this->oImapClient->MessageSimpleESort($aSortTypes, $sSearchCriterias)['ALL'];
$aResultUids = $this->oImapClient->MessageSimpleSort(array($sSort ?: 'REVERSE DATE'), $sSearchCriterias); $aResultUids = $this->oImapClient->MessageSimpleSort($aSortTypes, $sSearchCriterias);
} else { } else {
// $this->oImapClient->hasCapability('ESEARCH') // $this->oImapClient->hasCapability('ESEARCH')
// $aResultUids = $this->oImapClient->MessageSimpleESearch($sSearchCriterias, null, true, \MailSo\Base\Utils::IsAscii($sSearchCriterias) ? '' : 'UTF-8') // $aResultUids = $this->oImapClient->MessageSimpleESearch($sSearchCriterias, null, true, \MailSo\Base\Utils::IsAscii($sSearchCriterias) ? '' : 'UTF-8')
@ -660,14 +669,14 @@ class MailClient
if ($oInfo->MESSAGES) { if ($oInfo->MESSAGES) {
if (0 < $this->oImapClient->Settings->message_list_limit && $this->oImapClient->Settings->message_list_limit < $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) { if ($this->oLogger) {
$this->oLogger->Write('List optimization (count: '.$oInfo->MESSAGES. $this->oLogger->Write('List optimization (count: '.$oInfo->MESSAGES.
', limit:'.$this->oImapClient->Settings->message_list_limit.')'); ', limit:'.$this->oImapClient->Settings->message_list_limit.')');
} }
if (\strlen($sSearch)) { if (\strlen($sSearch)) {
$aUids = $this->GetUids($oParams, $sSearch, $aUids = $this->GetUids($oParams, $sSearch, $oMessageCollection->FolderHash);
$oMessageCollection->FolderName, $oMessageCollection->FolderHash);
$oMessageCollection->totalEmails = \count($aUids); $oMessageCollection->totalEmails = \count($aUids);
if ($oMessageCollection->totalEmails) { if ($oMessageCollection->totalEmails) {
$this->MessageListByRequestIndexOrUids( $this->MessageListByRequestIndexOrUids(
@ -680,7 +689,8 @@ class MailClient
if (1 < $oInfo->MESSAGES) { if (1 < $oInfo->MESSAGES) {
$end = \max(1, $oInfo->MESSAGES - $oParams->iOffset); $end = \max(1, $oInfo->MESSAGES - $oParams->iOffset);
$start = \max(1, $end - $oParams->iLimit + 1); $start = \max(1, $end - $oParams->iLimit + 1);
$aRequestIndexes = \range($start, $end); // Attempt to sort REVERSE DATE
$aRequestIndexes = \range($end, $start);
} else { } else {
$aRequestIndexes = \array_slice([1], $oParams->iOffset, 1); $aRequestIndexes = \array_slice([1], $oParams->iOffset, 1);
} }
@ -688,7 +698,6 @@ class MailClient
} }
} else { } else {
$aUids = []; $aUids = [];
$bUseSortIfSupported = $oParams->bUseSortIfSupported && $this->oImapClient->hasCapability('SORT');
if ($bUseThreads) { if ($bUseThreads) {
$aAllThreads = $this->MessageListThreadsMap($oMessageCollection->FolderName, $oMessageCollection->FolderHash, $oParams->oCacher); $aAllThreads = $this->MessageListThreadsMap($oMessageCollection->FolderName, $oMessageCollection->FolderHash, $oParams->oCacher);
$oMessageCollection->totalThreads = \count($aAllThreads); $oMessageCollection->totalThreads = \count($aAllThreads);
@ -703,8 +712,7 @@ class MailClient
} }
} }
} else { } else {
$aUids = $this->GetUids($oParams, '', $aUids = $this->GetUids($oParams, '', $oMessageCollection->FolderHash, $oParams->bUseSortIfSupported);
$oMessageCollection->FolderName, $oMessageCollection->FolderHash, $bUseSortIfSupported, $oParams->sSort);
// Remove all threaded UID's except the most recent of each thread // Remove all threaded UID's except the most recent of each thread
$threadedUids = []; $threadedUids = [];
foreach ($aAllThreads as $aMap) { foreach ($aAllThreads as $aMap) {
@ -714,13 +722,11 @@ class MailClient
$aUids = \array_diff($aUids, $threadedUids); $aUids = \array_diff($aUids, $threadedUids);
} }
} else { } else {
$aUids = $this->GetUids($oParams, '', $aUids = $this->GetUids($oParams, '', $oMessageCollection->FolderHash, $oParams->bUseSortIfSupported);
$oMessageCollection->FolderName, $oMessageCollection->FolderHash, $bUseSortIfSupported, $oParams->sSort);
} }
if ($aUids && \strlen($sSearch)) { if ($aUids && \strlen($sSearch)) {
$aSearchedUids = $this->GetUids($oParams, $sSearch, $aSearchedUids = $this->GetUids($oParams, $sSearch, $oMessageCollection->FolderHash);
$oMessageCollection->FolderName, $oMessageCollection->FolderHash);
if ($bUseThreads && !$oParams->iThreadUid) { if ($bUseThreads && !$oParams->iThreadUid) {
$matchingThreadUids = []; $matchingThreadUids = [];
foreach ($aAllThreads as $aMap) { foreach ($aAllThreads as $aMap) {

View file

@ -43,6 +43,8 @@ class MessageCollection extends \MailSo\Base\Collection
// public bool $Filtered = false; // public bool $Filtered = false;
public bool $Limited = false;
public function append($oMessage, bool $bToTop = false) : void public function append($oMessage, bool $bToTop = false) : void
{ {
assert($oMessage instanceof Message); assert($oMessage instanceof Message);
@ -61,14 +63,15 @@ class MessageCollection extends \MailSo\Base\Collection
'totalEmails' => $this->totalEmails, 'totalEmails' => $this->totalEmails,
'totalThreads' => $this->totalThreads, 'totalThreads' => $this->totalThreads,
'Folder' => $this->FolderName, 'Folder' => $this->FolderName,
'FolderHash' => $this->FolderHash, 'folderHash' => $this->FolderHash,
'FolderInfo' => $this->FolderInfo, 'folderInfo' => $this->FolderInfo,
'ThreadUid' => $this->ThreadUid, 'threadUid' => $this->ThreadUid,
'NewMessages' => $this->NewMessages, 'newMessages' => $this->NewMessages,
// 'Filtered' => $this->Filtered, // 'Filtered' => $this->Filtered,
'Offset' => $this->Offset, 'offset' => $this->Offset,
'Limit' => $this->Limit, 'limit' => $this->Limit,
'Search' => $this->Search 'search' => $this->Search,
'limited' => $this->Limited
)); ));
} }
} }

View file

@ -30,27 +30,27 @@ trait Messages
// $oParams->sHash = (string) $aValues['Hash']; // $oParams->sHash = (string) $aValues['Hash'];
$oParams->sFolderName = (string) $aValues['Folder']; $oParams->sFolderName = (string) $aValues['Folder'];
$oParams->iLimit = $aValues['Limit']; $oParams->iLimit = $aValues['limit'];
$oParams->iOffset = $aValues['Offset']; $oParams->iOffset = $aValues['offset'];
$oParams->sSearch = (string) $aValues['Search']; $oParams->sSearch = (string) $aValues['search'];
$oParams->sSort = (string) $aValues['Sort']; $oParams->sSort = (string) $aValues['sort'];
if (isset($aValues['UidNext'])) { if (isset($aValues['uidNext'])) {
$oParams->iPrevUidNext = $aValues['UidNext']; $oParams->iPrevUidNext = $aValues['uidNext'];
} }
$oParams->bUseThreads = !empty($aValues['UseThreads']); $oParams->bUseThreads = !empty($aValues['useThreads']);
if ($oParams->bUseThreads && isset($aValues['ThreadUid'])) { if ($oParams->bUseThreads && isset($aValues['threadUid'])) {
$oParams->iThreadUid = $aValues['ThreadUid']; $oParams->iThreadUid = $aValues['threadUid'];
} }
} else { } else {
$oParams->sFolderName = $this->GetActionParam('Folder', ''); $oParams->sFolderName = $this->GetActionParam('Folder', '');
$oParams->iOffset = $this->GetActionParam('Offset', 0); $oParams->iOffset = $this->GetActionParam('offset', 0);
$oParams->iLimit = $this->GetActionParam('Limit', 10); $oParams->iLimit = $this->GetActionParam('limit', 10);
$oParams->sSearch = $this->GetActionParam('Search', ''); $oParams->sSearch = $this->GetActionParam('search', '');
$oParams->sSort = $this->GetActionParam('Sort', ''); $oParams->sSort = $this->GetActionParam('sort', '');
$oParams->iPrevUidNext = $this->GetActionParam('UidNext', 0); $oParams->iPrevUidNext = $this->GetActionParam('uidNext', 0);
$oParams->bUseThreads = !empty($this->GetActionParam('UseThreads', '0')); $oParams->bUseThreads = !empty($this->GetActionParam('useThreads', '0'));
if ($oParams->bUseThreads) { if ($oParams->bUseThreads) {
$oParams->iThreadUid = $this->GetActionParam('ThreadUid', ''); $oParams->iThreadUid = $this->GetActionParam('threadUid', '');
} }
} }

View file

@ -93,10 +93,10 @@
<li role="presentation" data-sort="REVERSE SUBJECT" data-bind="click: changeSort"> <li role="presentation" data-sort="REVERSE SUBJECT" data-bind="click: changeSort">
<a href="#" tabindex="-1" data-icon="𝐒⬆" data-i18n="MESSAGE_LIST/SORT_SUBJECT_DESC"></a> <a href="#" tabindex="-1" data-icon="𝐒⬆" data-i18n="MESSAGE_LIST/SORT_SUBJECT_DESC"></a>
</li> </li>
<li class="dividerbar" role="presentation" data-sort="FROM REVERSE DATE" data-bind="click: changeSort"> <li class="dividerbar" role="presentation" data-sort="FROM" data-bind="click: changeSort">
<a href="#" tabindex="-1" data-icon="@⬇" data-i18n="MESSAGE_LIST/SORT_FROM_ASC"></a> <a href="#" tabindex="-1" data-icon="@⬇" data-i18n="MESSAGE_LIST/SORT_FROM_ASC"></a>
</li> </li>
<li role="presentation" data-sort="REVERSE FROM REVERSE DATE" data-bind="click: changeSort"> <li role="presentation" data-sort="REVERSE FROM" data-bind="click: changeSort">
<a href="#" tabindex="-1" data-icon="@⬆" data-i18n="MESSAGE_LIST/SORT_FROM_DESC"></a> <a href="#" tabindex="-1" data-icon="@⬆" data-i18n="MESSAGE_LIST/SORT_FROM_DESC"></a>
</li> </li>
</menu> </menu>