mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-09-02 05:59:21 +03:00
New thread list logic (step 1)
This commit is contained in:
parent
c73eb76816
commit
b656b6365b
10 changed files with 186 additions and 78 deletions
|
|
@ -214,12 +214,13 @@
|
|||
);
|
||||
}
|
||||
|
||||
}, FolderStore.currentFolderFullNameRaw(), iOffset, SettingsStore.messagesPerPage(), MessageStore.messageListSearch());
|
||||
}, FolderStore.currentFolderFullNameRaw(), iOffset, SettingsStore.messagesPerPage(),
|
||||
MessageStore.messageListSearch(), MessageStore.messageListThreadUid());
|
||||
};
|
||||
|
||||
AppUser.prototype.recacheInboxMessageList = function ()
|
||||
{
|
||||
Remote.messageList(Utils.emptyFunction, Cache.getFolderInboxName(), 0, SettingsStore.messagesPerPage(), '', true);
|
||||
Remote.messageList(Utils.emptyFunction, Cache.getFolderInboxName(), 0, SettingsStore.messagesPerPage(), '', '', true);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -257,23 +257,30 @@
|
|||
* @param {string} sFolder
|
||||
* @param {number=} iPage = 1
|
||||
* @param {string=} sSearch = ''
|
||||
* @param {string=} sThreadUid = ''
|
||||
* @return {string}
|
||||
*/
|
||||
Links.prototype.mailBox = function (sFolder, iPage, sSearch)
|
||||
Links.prototype.mailBox = function (sFolder, iPage, sSearch, sThreadUid)
|
||||
{
|
||||
iPage = Utils.isNormal(iPage) ? Utils.pInt(iPage) : 1;
|
||||
sSearch = Utils.pString(sSearch);
|
||||
|
||||
var sResult = this.sBase + 'mailbox/';
|
||||
var
|
||||
sResult = this.sBase + 'mailbox/',
|
||||
iThreadUid = Utils.pInt(sThreadUid)
|
||||
;
|
||||
|
||||
if ('' !== sFolder)
|
||||
{
|
||||
sResult += encodeURI(sFolder);
|
||||
sResult += encodeURI(sFolder) + (0 < iThreadUid ? '|' + iThreadUid : '');
|
||||
}
|
||||
|
||||
if (1 < iPage)
|
||||
{
|
||||
sResult = sResult.replace(/[\/]+$/, '');
|
||||
sResult += '/p' + iPage;
|
||||
}
|
||||
|
||||
if ('' !== sSearch)
|
||||
{
|
||||
sResult = sResult.replace(/[\/]+$/, '');
|
||||
|
|
|
|||
|
|
@ -332,10 +332,10 @@
|
|||
* @param {number=} iOffset = 0
|
||||
* @param {number=} iLimit = 20
|
||||
* @param {string=} sSearch = ''
|
||||
* @param {boolean=} bSilent = false
|
||||
* @param {string=} sThreadUid = ''
|
||||
* @param {boolean=} bSilent = false
|
||||
*/
|
||||
RemoteUserAjax.prototype.messageList = function (fCallback, sFolderFullNameRaw, iOffset, iLimit, sSearch, bSilent, sThreadUid)
|
||||
RemoteUserAjax.prototype.messageList = function (fCallback, sFolderFullNameRaw, iOffset, iLimit, sSearch, sThreadUid, bSilent)
|
||||
{
|
||||
sFolderFullNameRaw = Utils.pString(sFolderFullNameRaw);
|
||||
|
||||
|
|
|
|||
|
|
@ -75,15 +75,23 @@
|
|||
MailBoxUserScreen.prototype.onRoute = function (sFolderHash, iPage, sSearch)
|
||||
{
|
||||
var
|
||||
sFolderFullNameRaw = Cache.getFolderFullNameRaw(sFolderHash),
|
||||
oFolder = Cache.getFolderFromCacheList(sFolderFullNameRaw)
|
||||
sThreadUid = sFolderHash.replace(/^(.+)\|([\d]+)$/, '$2'),
|
||||
oFolder = Cache.getFolderFromCacheList(Cache.getFolderFullNameRaw(
|
||||
sFolderHash.replace(/\|([\d]+)$/, '')))
|
||||
;
|
||||
|
||||
if (oFolder)
|
||||
{
|
||||
if (sFolderHash === sThreadUid)
|
||||
{
|
||||
sThreadUid = '';
|
||||
}
|
||||
|
||||
FolderStore.currentFolder(oFolder);
|
||||
|
||||
MessageStore.messageListPage(iPage);
|
||||
MessageStore.messageListSearch(sSearch);
|
||||
MessageStore.messageListThreadUid(sThreadUid);
|
||||
|
||||
require('App/User').reloadMessageList();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
this.messageListCount = ko.observable(0);
|
||||
this.messageListSearch = ko.observable('');
|
||||
this.messageListThreadUid = ko.observable('');
|
||||
this.messageListPage = ko.observable(1);
|
||||
this.messageListError = ko.observable('');
|
||||
|
||||
|
|
@ -813,6 +814,7 @@
|
|||
this.messageListCount(iCount);
|
||||
this.messageListSearch(Utils.isNormal(oData.Result.Search) ? oData.Result.Search : '');
|
||||
this.messageListPage(window.Math.ceil((iOffset / SettingsStore.messagesPerPage()) + 1));
|
||||
this.messageListThreadUid(Utils.isNormal(oData.Result.ThreadUid) ? Utils.pString(oData.Result.ThreadUid) : '');
|
||||
|
||||
this.messageListEndFolder(Utils.isNormal(oData.Result.Folder) ? oData.Result.Folder : '');
|
||||
this.messageListEndSearch(Utils.isNormal(oData.Result.Search) ? oData.Result.Search : '');
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@
|
|||
this.selectorMessageFocused = MessageStore.selectorMessageFocused;
|
||||
this.isMessageSelected = MessageStore.isMessageSelected;
|
||||
this.messageListSearch = MessageStore.messageListSearch;
|
||||
this.messageListThreadUid = MessageStore.messageListThreadUid;
|
||||
this.messageListError = MessageStore.messageListError;
|
||||
this.folderMenuForMove = FolderStore.folderMenuForMove;
|
||||
|
||||
|
|
@ -611,7 +612,8 @@
|
|||
kn.setHash(Links.mailBox(
|
||||
FolderStore.currentFolderFullNameHash(),
|
||||
oPage.value,
|
||||
MessageStore.messageListSearch()
|
||||
MessageStore.messageListSearch(),
|
||||
MessageStore.messageListThreadUid()
|
||||
));
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1911,6 +1911,88 @@ class MailClient
|
|||
return $oMessageCollection->GetAsArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \MailSo\Cache\CacheClient|null $oCacher
|
||||
* @param string $sSearch
|
||||
* @param string $sFolderName
|
||||
* @param string $sFolderHash
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function GetUids($oCacher, $sSearch, $sFolderName, $sFolderHash)
|
||||
{
|
||||
$aResultUids = false;
|
||||
$bUidsFromCacher = false;
|
||||
$bUseCacheAfterSearch = true;
|
||||
|
||||
$sSerializedHash = '';
|
||||
$sSerializedLog = '';
|
||||
|
||||
$bUseSortIfSupported = !!$this->oImapClient->IsSupported('SORT');
|
||||
|
||||
if (0 < \strlen($sSearch))
|
||||
{
|
||||
$bUseSortIfSupported = false;
|
||||
}
|
||||
|
||||
$sSearchCriterias = $this->getImapSearchCriterias($sSearch, 0, $bUseCacheAfterSearch);
|
||||
if ($bUseCacheAfterSearch && $oCacher && $oCacher->IsInited())
|
||||
{
|
||||
$sSerializedHash = 'GetUids/'.
|
||||
($bUseSortIfSupported ? 'S': 'N').'/'.
|
||||
$this->GenerateImapClientHash().'/'.
|
||||
$sFolderName.'/'.$sSearchCriterias;
|
||||
|
||||
$sSerializedLog = '"'.$sFolderName.'" / '.$sSearchCriterias.'';
|
||||
|
||||
$sSerialized = $oCacher->Get($sSerializedHash);
|
||||
if (!empty($sSerialized))
|
||||
{
|
||||
$aSerialized = @\json_decode($sSerialized, true);
|
||||
if (\is_array($aSerialized) && isset($aSerialized['FolderHash'], $aSerialized['Uids']) &&
|
||||
$sFolderHash === $aSerialized['FolderHash'] &&
|
||||
\is_array($aSerialized['Uids'])
|
||||
)
|
||||
{
|
||||
if ($this->oLogger)
|
||||
{
|
||||
$this->oLogger->Write('Get Serialized UIDS from cache ('.$sSerializedLog.') [count:'.\count($aSerialized['Uids']).']');
|
||||
}
|
||||
|
||||
$aResultUids = $aSerialized['Uids'];
|
||||
$bUidsFromCacher = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!\is_array($aResultUids))
|
||||
{
|
||||
$aResultUids = $bUseSortIfSupported ?
|
||||
$this->oImapClient->MessageSimpleSort(array('REVERSE ARRIVAL'), $sSearchCriterias, true) :
|
||||
$this->oImapClient->MessageSimpleSearch($sSearchCriterias, true)
|
||||
;
|
||||
|
||||
if (!$bUidsFromCacher && $bUseCacheAfterSearch && \is_array($aResultUids) && $oCacher && $oCacher->IsInited() && 0 < \strlen($sSerializedHash))
|
||||
{
|
||||
$oCacher->Set($sSerializedHash, @\json_encode(array(
|
||||
'FolderHash' => $sFolderHash,
|
||||
'Uids' => $aResultUids
|
||||
)));
|
||||
|
||||
if ($this->oLogger)
|
||||
{
|
||||
$this->oLogger->Write('Save Serialized UIDS to cache ('.$sSerializedLog.') [count:'.\count($aResultUids).']');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $aResultUids;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sFolderName
|
||||
* @param int $iOffset = 0
|
||||
|
|
@ -1930,8 +2012,7 @@ class MailClient
|
|||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function MessageList($sFolderName, $iOffset = 0, $iLimit = 10, $sSearch = '', $sPrevUidNext = '', $oCacher = null,
|
||||
$bUseSortIfSupported = false, $bUseThreadSortIfSupported = false, $bUseESearchOrESortRequest = false,
|
||||
$sThreadUid = '')
|
||||
$bUseSortIfSupported = false, $bUseThreadSortIfSupported = false, $sThreadUid = '')
|
||||
{
|
||||
$sSearch = \trim($sSearch);
|
||||
if (!\MailSo\Base\Validator::RangeInt($iOffset, 0) ||
|
||||
|
|
@ -1947,10 +2028,14 @@ class MailClient
|
|||
$oMessageCollection->Offset = $iOffset;
|
||||
$oMessageCollection->Limit = $iLimit;
|
||||
$oMessageCollection->Search = $sSearch;
|
||||
$oMessageCollection->ThreadUid = $sThreadUid;
|
||||
|
||||
$aThreads = array();
|
||||
$aUids = array();
|
||||
$mAllSortedUids = null;
|
||||
$mAllThreads = null;
|
||||
|
||||
$iThreadUid = empty($sThreadUid) ? 0 : (int) $sThreadUid;
|
||||
|
||||
$iMessageCount = 0;
|
||||
$iMessageRealCount = 0;
|
||||
$iMessageUnseenCount = 0;
|
||||
$sUidNext = '0';
|
||||
|
|
@ -1971,11 +2056,15 @@ class MailClient
|
|||
}
|
||||
|
||||
$this->initFolderValues($sFolderName, $iMessageRealCount, $iMessageUnseenCount, $sUidNext);
|
||||
$iMessageCount = $iMessageRealCount;
|
||||
|
||||
$oMessageCollection->FolderHash = $this->GenerateFolderHash($sFolderName, $iMessageRealCount, $iMessageUnseenCount, $sUidNext);
|
||||
$oMessageCollection->UidNext = $sUidNext;
|
||||
$oMessageCollection->NewMessages = $this->getFolderNextMessageInformation($sFolderName, $sPrevUidNext, $sUidNext);
|
||||
|
||||
if (empty($sThreadUid) && 0 < \strlen($sPrevUidNext) && 'INBOX' === $sFolderName)
|
||||
{
|
||||
$oMessageCollection->NewMessages = $this->getFolderNextMessageInformation(
|
||||
$sFolderName, $sPrevUidNext, $sUidNext);
|
||||
}
|
||||
|
||||
$bSearch = false;
|
||||
$bMessageListOptimization = 0 < \MailSo\Config::$MessageListCountLimitTrigger &&
|
||||
|
|
@ -1985,104 +2074,98 @@ class MailClient
|
|||
{
|
||||
$bUseSortIfSupported = false;
|
||||
$bUseThreadSortIfSupported = false;
|
||||
$bUseESearchOrESortRequest = false;
|
||||
}
|
||||
|
||||
if (0 < $iMessageRealCount)
|
||||
{
|
||||
$bIndexAsUid = false;
|
||||
$aIndexOrUids = array();
|
||||
$mAllSortedUids = $this->GetUids($oCacher, '', $oMessageCollection->FolderName, $oMessageCollection->FolderHash);
|
||||
|
||||
// $mThreads = $this->MessageListThreadsMap($sFolderName, $sFolderHash, array(), $oCacher, true);
|
||||
// if (\is_array($mThreads))
|
||||
// {
|
||||
//
|
||||
// }
|
||||
$mAllThreads = $bUseThreadSortIfSupported ? $this->MessageListThreadsMap(
|
||||
$oMessageCollection->FolderName, $oMessageCollection->FolderHash, $mAllSortedUids, $oCacher) : null;
|
||||
|
||||
if (0 < \strlen($sSearch))
|
||||
if ($bUseThreadSortIfSupported && 0 < $iThreadUid && \is_array($mAllThreads))
|
||||
{
|
||||
$aIndexOrUids = $this->getSearchUidsResult($sSearch,
|
||||
$oMessageCollection->FolderName, $oMessageCollection->FolderHash,
|
||||
$bUseSortIfSupported, $bUseESearchOrESortRequest, $oCacher);
|
||||
$aUids = array();
|
||||
$aUids = \is_array($mAllThreads[$iThreadUid]) ?
|
||||
$mAllThreads[$iThreadUid] : array();
|
||||
|
||||
$bIndexAsUid = true;
|
||||
if (\in_array($iThreadUid, $mAllSortedUids))
|
||||
{
|
||||
\array_unshift($aUids, $iThreadUid);
|
||||
}
|
||||
}
|
||||
else if ($bUseThreadSortIfSupported && \is_array($mAllThreads))
|
||||
{
|
||||
$aUids = \array_keys($mAllThreads);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($bUseThreadSortIfSupported && 1 < $iMessageCount)
|
||||
$bUseThreadSortIfSupported = false;
|
||||
$aUids = $mAllSortedUids;
|
||||
}
|
||||
|
||||
if (0 < \strlen($sSearch) && \is_array($aUids))
|
||||
{
|
||||
$aSearchedUids = $this->GetUids($oCacher, $sSearch, $oMessageCollection->FolderName, $oMessageCollection->FolderHash);
|
||||
if (\is_array($aSearchedUids) && 0 < \count($aSearchedUids))
|
||||
{
|
||||
$aIndexOrUids = $this->getSearchUidsResult('',
|
||||
$oMessageCollection->FolderName, $oMessageCollection->FolderHash,
|
||||
$bUseSortIfSupported, $bUseESearchOrESortRequest, $oCacher);
|
||||
$aFlippedSearchedUids = \array_flip($aSearchedUids);
|
||||
|
||||
$aThreads = $this->MessageListThreadsMap(
|
||||
$oMessageCollection->FolderName, $oMessageCollection->FolderHash,
|
||||
$aIndexOrUids, $oCacher);
|
||||
$bSearch = true;
|
||||
$aNewUids = array();
|
||||
|
||||
$aNewIndexOrUids = array();
|
||||
foreach ($aIndexOrUids as $iUid)
|
||||
foreach ($aUids as $iUid)
|
||||
{
|
||||
if (isset($aThreads[$iUid]))
|
||||
if (isset($aFlippedSearchedUids[$iUid]))
|
||||
{
|
||||
$aNewIndexOrUids[] = $iUid;
|
||||
$aNewUids[] = $iUid;
|
||||
}
|
||||
else if ($bUseThreadSortIfSupported && 0 === $iThreadUid && isset($mAllThreads[$iUid]) && \is_array($mAllThreads[$iUid]))
|
||||
{
|
||||
foreach ($mAllThreads[$iUid] as $iSubUid)
|
||||
{
|
||||
if (isset($aFlippedSearchedUids[$iSubUid]))
|
||||
{
|
||||
$aNewUids[] = $iUid;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$aIndexOrUids = $aNewIndexOrUids;
|
||||
unset($aNewIndexOrUids);
|
||||
|
||||
$iMessageCount = \count($aIndexOrUids);
|
||||
$bIndexAsUid = true;
|
||||
$aUids = \array_unique($aNewUids);
|
||||
unset($aNewUids);
|
||||
}
|
||||
else
|
||||
{
|
||||
$aIndexOrUids = array(1);
|
||||
$bIndexAsUid = false;
|
||||
|
||||
if (1 < $iMessageCount)
|
||||
{
|
||||
if (0 === \MailSo\Config::$MessageListDateFilter &&
|
||||
($bMessageListOptimization || !$bUseSortIfSupported))
|
||||
{
|
||||
$aIndexOrUids = \array_reverse(\range(1, $iMessageCount));
|
||||
}
|
||||
else
|
||||
{
|
||||
$aIndexOrUids = $this->getSearchUidsResult('',
|
||||
$oMessageCollection->FolderName, $oMessageCollection->FolderHash,
|
||||
$bUseSortIfSupported, $bUseESearchOrESortRequest, $oCacher);
|
||||
|
||||
$bIndexAsUid = true;
|
||||
}
|
||||
}
|
||||
$aUids = array();
|
||||
}
|
||||
}
|
||||
|
||||
if (\is_array($aIndexOrUids))
|
||||
if (\is_array($aUids))
|
||||
{
|
||||
$oMessageCollection->MessageCount = $iMessageRealCount;
|
||||
$oMessageCollection->MessageUnseenCount = $iMessageUnseenCount;
|
||||
$oMessageCollection->MessageResultCount = 0 === \strlen($sSearch)
|
||||
? $iMessageCount : \count($aIndexOrUids);
|
||||
$oMessageCollection->MessageResultCount = \count($aUids);
|
||||
|
||||
if (0 < \count($aIndexOrUids))
|
||||
if (0 < \count($aUids))
|
||||
{
|
||||
$iOffset = (0 > $iOffset) ? 0 : $iOffset;
|
||||
$aRequestIndexOrUids = \array_slice($aIndexOrUids, $iOffset, $iLimit);
|
||||
$aRequestUids = \array_slice($aUids, $iOffset, $iLimit);
|
||||
|
||||
$this->MessageListByRequestIndexOrUids($oMessageCollection, $aRequestIndexOrUids, $bIndexAsUid);
|
||||
$this->MessageListByRequestIndexOrUids($oMessageCollection, $aRequestUids, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$bSearch && $bUseThreadSortIfSupported && 0 < \count($aThreads))
|
||||
if ($bUseThreadSortIfSupported && 0 === $iThreadUid && \is_array($mAllThreads) && 0 < \count($mAllThreads))
|
||||
{
|
||||
$oMessageCollection->ForeachList(function (/* @var $oMessage \MailSo\Mail\Message */ $oMessage) use ($aThreads) {
|
||||
$oMessageCollection->ForeachList(function (/* @var $oMessage \MailSo\Mail\Message */ $oMessage) use ($mAllThreads) {
|
||||
|
||||
$iUid = $oMessage->Uid();
|
||||
if (isset($aThreads[$iUid]) && \is_array($aThreads[$iUid]) && 0 < \count($aThreads[$iUid]))
|
||||
if (isset($mAllThreads[$iUid]) && \is_array($mAllThreads[$iUid]) && 0 < \count($mAllThreads[$iUid]))
|
||||
{
|
||||
$aSubThreads = $aThreads[$iUid];
|
||||
$aSubThreads = $mAllThreads[$iUid];
|
||||
\array_unshift($aSubThreads, $iUid);
|
||||
|
||||
$oMessage->SetThreads(\array_map('trim', $aSubThreads));
|
||||
|
|
|
|||
|
|
@ -62,6 +62,11 @@ class MessageCollection extends \MailSo\Base\Collection
|
|||
*/
|
||||
public $UidNext;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $ThreadUid;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
|
|
@ -108,8 +113,9 @@ class MessageCollection extends \MailSo\Base\Collection
|
|||
$this->Limit = 0;
|
||||
$this->Search = '';
|
||||
$this->UidNext = '';
|
||||
$this->ThreadUid = '';
|
||||
$this->NewMessages = array();
|
||||
|
||||
|
||||
$this->LastCollapsedThreadUids = array();
|
||||
|
||||
return $this;
|
||||
|
|
|
|||
|
|
@ -5564,7 +5564,7 @@ class Actions
|
|||
$sFolder, $iOffset, $iLimit, $sSearch, $sUidNext,
|
||||
$this->cacherForUids(),
|
||||
!!$this->Config()->Get('labs', 'use_imap_sort', false),
|
||||
$bUseThreads, !!$this->Config()->Get('labs', 'use_imap_esearch_esort', false),
|
||||
$bUseThreads,
|
||||
$sThreadUid
|
||||
);
|
||||
}
|
||||
|
|
@ -9372,8 +9372,8 @@ class Actions
|
|||
'Folder' => $mResponse->FolderName,
|
||||
'FolderHash' => $mResponse->FolderHash,
|
||||
'UidNext' => $mResponse->UidNext,
|
||||
'ThreadUid' => $mResponse->ThreadUid,
|
||||
'NewMessages' => $this->responseObject($mResponse->NewMessages),
|
||||
// 'LastCollapsedThreadUids' => $mResponse->LastCollapsedThreadUids,
|
||||
'Offset' => $mResponse->Offset,
|
||||
'Limit' => $mResponse->Limit,
|
||||
'Search' => $mResponse->Search
|
||||
|
|
|
|||
|
|
@ -282,7 +282,6 @@ Enables caching in the system'),
|
|||
'use_app_debug_js' => array(false),
|
||||
'use_app_debug_css' => array(false),
|
||||
'use_imap_sort' => array(true),
|
||||
'use_imap_esearch_esort' => array(true),
|
||||
'use_imap_force_selection' => array(false),
|
||||
'use_imap_list_subscribe' => array(true),
|
||||
'use_imap_thread' => array(true),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue