New thread list logic (step 1)

This commit is contained in:
RainLoop Team 2015-04-20 23:49:51 +04:00
parent c73eb76816
commit b656b6365b
10 changed files with 186 additions and 78 deletions

View file

@ -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);
};
/**

View file

@ -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(/[\/]+$/, '');

View file

@ -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);

View file

@ -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();
}

View file

@ -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 : '');

View file

@ -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()
));
}
};

View file

@ -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));

View file

@ -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;

View file

@ -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

View file

@ -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),