mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-13 03:27:39 +03:00
Resolve #1028
This commit is contained in:
parent
1f8fddd3f4
commit
26fb2cf9fb
6 changed files with 56 additions and 35 deletions
|
|
@ -113,14 +113,12 @@ export class MessageModel extends AbstractModel {
|
|||
|
||||
// rfc8621
|
||||
id: '',
|
||||
// threadId: '',
|
||||
|
||||
hasUnseenSubMessage: false,
|
||||
hasFlaggedSubMessage: false
|
||||
// threadId: ''
|
||||
});
|
||||
|
||||
this.attachments = ko.observableArray(new AttachmentCollectionModel);
|
||||
this.threads = ko.observableArray();
|
||||
this.threadUnseen = ko.observableArray();
|
||||
this.unsubsribeLinks = ko.observableArray();
|
||||
this.flags = ko.observableArray();
|
||||
|
||||
|
|
@ -128,6 +126,7 @@ export class MessageModel extends AbstractModel {
|
|||
attachmentIconClass: () =>
|
||||
this.encrypted() ? 'icon-lock' : FileInfo.getAttachmentsIconClass(this.attachments()),
|
||||
threadsLen: () => rl.app.messageList.threadUid() ? 0 : this.threads().length,
|
||||
threadUnseenLen: () => rl.app.messageList.threadUid() ? 0 : this.threadUnseen().length,
|
||||
|
||||
isUnseen: () => !this.flags().includes('\\seen'),
|
||||
isFlagged: () => this.flags().includes('\\flagged'),
|
||||
|
|
@ -238,9 +237,7 @@ export class MessageModel extends AbstractModel {
|
|||
focused: this.focused(),
|
||||
priorityHigh: this.priority() === 1,
|
||||
withAttachments: !!this.attachments().length,
|
||||
// hasChildrenMessage: 1 < this.threadsLen(),
|
||||
hasUnseenSubMessage: this.hasUnseenSubMessage(),
|
||||
hasFlaggedSubMessage: this.hasFlaggedSubMessage()
|
||||
// hasChildrenMessage: 1 < this.threadsLen()
|
||||
}, (key, value) => value && classes.push(key));
|
||||
flags && this.flags().forEach(value => classes.push('msgflag-'+value));
|
||||
return classes.join(' ');
|
||||
|
|
|
|||
|
|
@ -289,16 +289,6 @@
|
|||
margin-right: 0.25em;
|
||||
}
|
||||
|
||||
&.hasUnseenSubMessage {
|
||||
background-color: rgba(255, 255, 64, 0.15);
|
||||
border-left-color: lighten(orange, 30%);
|
||||
border-right-color: lighten(orange, 30%) !important;
|
||||
&.focused {
|
||||
border-left-color: darken(orange, 10%);
|
||||
border-right-color: darken(orange, 10%) !important;
|
||||
}
|
||||
}
|
||||
|
||||
&.unseen {
|
||||
background-color: rgba(255, 255, 64, 0.15);
|
||||
border-left-color: orange;
|
||||
|
|
@ -312,6 +302,9 @@
|
|||
border-right-color: darken(orange, 10%) !important;
|
||||
}
|
||||
}
|
||||
[data-unseen] {
|
||||
background-color: rgba(255, 255, 64, 0.15);
|
||||
}
|
||||
|
||||
&.checked {
|
||||
border-left-color: lighten(#398CF2, 10%);
|
||||
|
|
|
|||
|
|
@ -446,7 +446,8 @@ class MailClient
|
|||
* @throws \MailSo\Net\Exceptions\*
|
||||
* @throws \MailSo\Imap\Exceptions\*
|
||||
*/
|
||||
protected function MessageListByRequestIndexOrUids(MessageCollection $oMessageCollection, SequenceSet $oRange, array &$aAllThreads = []) : void
|
||||
protected function MessageListByRequestIndexOrUids(MessageCollection $oMessageCollection, SequenceSet $oRange,
|
||||
array &$aAllThreads = [], array &$aUnseenUIDs = []) : void
|
||||
{
|
||||
if (\count($oRange)) {
|
||||
$aFetchIterator = $this->oImapClient->FetchIterate(array(
|
||||
|
|
@ -472,6 +473,7 @@ class MailClient
|
|||
foreach ($aAllThreads as $aMap) {
|
||||
if (\in_array($iUid, $aMap)) {
|
||||
$oMessage->SetThreads($aMap);
|
||||
$oMessage->SetThreadUnseen(\array_values(\array_intersect($aUnseenUIDs, $aMap)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -490,7 +492,7 @@ class MailClient
|
|||
* @throws \MailSo\Imap\Exceptions\*
|
||||
*/
|
||||
private function GetUids(MessageListParams $oParams, string $sSearch,
|
||||
string $sFolderHash, bool $bUseSort = false) : array
|
||||
FolderInformation $oInfo, bool $bUseSort = false) : array
|
||||
{
|
||||
$oCacher = $oParams->oCacher;
|
||||
$sFolderName = $oParams->sFolderName;
|
||||
|
|
@ -562,7 +564,7 @@ class MailClient
|
|||
if (!empty($sSerialized)) {
|
||||
$aSerialized = \json_decode($sSerialized, true);
|
||||
if (\is_array($aSerialized) && isset($aSerialized['FolderHash'], $aSerialized['Uids']) &&
|
||||
$sFolderHash === $aSerialized['FolderHash'] &&
|
||||
$oInfo->etag === $aSerialized['FolderHash'] &&
|
||||
\is_array($aSerialized['Uids'])
|
||||
) {
|
||||
$this->logWrite('Get Serialized '.($bReturnUid?'UIDS':'IDS').' from cache ('.$sSerializedLog.') [count:'.\count($aSerialized['Uids']).']');
|
||||
|
|
@ -594,7 +596,7 @@ class MailClient
|
|||
|
||||
if ($bUseCacheAfterSearch) {
|
||||
$oCacher->Set($sSerializedHash, \json_encode(array(
|
||||
'FolderHash' => $sFolderHash,
|
||||
'FolderHash' => $oInfo->etag,
|
||||
'Uids' => $aResultUids
|
||||
)));
|
||||
|
||||
|
|
@ -604,6 +606,23 @@ class MailClient
|
|||
return $aResultUids;
|
||||
}
|
||||
|
||||
public function MessageListUnseen(MessageListParams $oParams, FolderInformation $oInfo) : array
|
||||
{
|
||||
$oUnseenParams = new MessageListParams;
|
||||
$oUnseenParams->sFolderName = $oParams->sFolderName;
|
||||
// $oUnseenParams->sSearch = $oParams->sSearch;
|
||||
// $oUnseenParams->sSort = $oParams->sSort;
|
||||
$oUnseenParams->oCacher = $oParams->oCacher;
|
||||
$oUnseenParams->bUseSort = false; // $oParams->bUseSort
|
||||
$oUnseenParams->bUseThreads = false; // $oParams->bUseThreads;
|
||||
$oUnseenParams->bHideDeleted = $oParams->bHideDeleted;
|
||||
// $oUnseenParams->iOffset = $oParams->iOffset;
|
||||
// $oUnseenParams->iLimit = $oParams->iLimit;
|
||||
// $oUnseenParams->iPrevUidNext = $oParams->iPrevUidNext;
|
||||
// $oUnseenParams->iThreadUid = $oParams->iThreadUid;
|
||||
return $this->GetUids($oUnseenParams, 'unseen', $oInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs SORT/SEARCH when $sSearch is provided
|
||||
* @throws \InvalidArgumentException
|
||||
|
|
@ -646,6 +665,7 @@ class MailClient
|
|||
if ($oInfo->MESSAGES) {
|
||||
$bUseSort = $oParams->bUseSort || $oParams->sSort;
|
||||
$aAllThreads = [];
|
||||
$aUnseenUIDs = [];
|
||||
$aUids = [];
|
||||
|
||||
$message_list_limit = $this->oImapClient->Settings->message_list_limit;
|
||||
|
|
@ -657,7 +677,7 @@ class MailClient
|
|||
$this->logWrite('List optimization (count: '.$oInfo->MESSAGES.', limit:'.$message_list_limit.')');
|
||||
if (\strlen($sSearch)) {
|
||||
// Don't use SORT for speed
|
||||
$aUids = $this->GetUids($oParams, $sSearch, $oInfo->etag/*, $bUseSort*/);
|
||||
$aUids = $this->GetUids($oParams, $sSearch, $oInfo/*, $bUseSort*/);
|
||||
} else {
|
||||
$bUseSort = $this->oImapClient->hasCapability('SORT');
|
||||
if (2 > $oInfo->MESSAGES) {
|
||||
|
|
@ -667,7 +687,7 @@ class MailClient
|
|||
$end = \min($oInfo->MESSAGES, \max(1, $oInfo->MESSAGES - $oParams->iOffset + $oParams->iLimit));
|
||||
$start = \max(1, $end - ($oParams->iLimit * 3) + 1);
|
||||
$oParams->oSequenceSet = new SequenceSet(\range($end, $start), false);
|
||||
$aRequestIndexes = $this->GetUids($oParams, '', $oInfo->etag, $bUseSort);
|
||||
$aRequestIndexes = $this->GetUids($oParams, '', $oInfo, $bUseSort);
|
||||
// Attempt to get the correct $oParams->iLimit slice
|
||||
$aRequestIndexes = \array_slice($aRequestIndexes, $oParams->iOffset ? $oParams->iLimit : 0, $oParams->iLimit);
|
||||
} else {
|
||||
|
|
@ -681,7 +701,7 @@ class MailClient
|
|||
} else {
|
||||
$aUids = ($bUseThreads && $oParams->iThreadUid)
|
||||
? [$oParams->iThreadUid]
|
||||
: $this->GetUids($oParams, '', $oInfo->etag, $bUseSort);
|
||||
: $this->GetUids($oParams, '', $oInfo, $bUseSort);
|
||||
|
||||
if ($bUseThreads) {
|
||||
$aAllThreads = $this->MessageListThreadsMap($oMessageCollection, $oParams->oCacher);
|
||||
|
|
@ -706,11 +726,13 @@ class MailClient
|
|||
$threadedUids = \array_merge($threadedUids, $aMap);
|
||||
}
|
||||
$aUids = \array_diff($aUids, $threadedUids);
|
||||
// Get all unseen
|
||||
$aUnseenUIDs = $this->MessageListUnseen($oParams, $oInfo);
|
||||
}
|
||||
}
|
||||
|
||||
if ($aUids && \strlen($sSearch)) {
|
||||
$aSearchedUids = $this->GetUids($oParams, $sSearch, $oInfo->etag/*, $bUseSort*/);
|
||||
$aSearchedUids = $this->GetUids($oParams, $sSearch, $oInfo/*, $bUseSort*/);
|
||||
if ($bUseThreads && !$oParams->iThreadUid) {
|
||||
$matchingThreadUids = [];
|
||||
foreach ($aAllThreads as $aMap) {
|
||||
|
|
@ -732,7 +754,7 @@ class MailClient
|
|||
if (\count($aUids)) {
|
||||
$oMessageCollection->totalEmails = \count($aUids);
|
||||
$aUids = \array_slice($aUids, $oParams->iOffset, $oParams->iLimit);
|
||||
$this->MessageListByRequestIndexOrUids($oMessageCollection, new SequenceSet($aUids), $aAllThreads);
|
||||
$this->MessageListByRequestIndexOrUids($oMessageCollection, new SequenceSet($aUids), $aAllThreads, $aUnseenUIDs);
|
||||
}
|
||||
} else {
|
||||
$this->logWrite('No messages in '.$oMessageCollection->FolderName);
|
||||
|
|
|
|||
|
|
@ -69,7 +69,8 @@ class Message implements \JsonSerializable
|
|||
// $aFlags = [],
|
||||
$aFlagsLowerCase = [],
|
||||
$UnsubsribeLinks = [],
|
||||
$aThreads = [];
|
||||
$aThreadUIDs = [],
|
||||
$aThreadUnseenUIDs = [];
|
||||
|
||||
private ?array $DraftInfo = null;
|
||||
private ?array $pgpSigned = null;
|
||||
|
|
@ -117,9 +118,14 @@ class Message implements \JsonSerializable
|
|||
$this->SpamScore = \intval(\max(0, \min(100, $value)));
|
||||
}
|
||||
|
||||
public function SetThreads(array $aThreads)
|
||||
public function SetThreads(array $aThreadUIDs)
|
||||
{
|
||||
$this->aThreads = $aThreads;
|
||||
$this->aThreadUIDs = $aThreadUIDs;
|
||||
}
|
||||
|
||||
public function SetThreadUnseen(array $aUnseenUIDs)
|
||||
{
|
||||
$this->aThreadUnseenUIDs = $aUnseenUIDs;
|
||||
}
|
||||
|
||||
public static function fromFetchResponse(string $sFolder, \MailSo\Imap\FetchResponse $oFetchResponse, ?\MailSo\Imap\BodyStructure $oBodyStructure = null) : self
|
||||
|
|
@ -456,7 +462,7 @@ class Message implements \JsonSerializable
|
|||
$this->sFolder,
|
||||
$this->Uid,
|
||||
\implode(',', $this->getFlags()),
|
||||
// \implode(',', $this->aThreads),
|
||||
// \implode(',', $this->aThreadUIDs),
|
||||
$sClientHash
|
||||
]));
|
||||
}
|
||||
|
|
@ -576,8 +582,11 @@ class Message implements \JsonSerializable
|
|||
$result['pgpEncrypted'] = $this->pgpEncrypted;
|
||||
}
|
||||
|
||||
if ($this->aThreads) {
|
||||
$result['threads'] = $this->aThreads;
|
||||
if ($this->aThreadUIDs) {
|
||||
$result['threads'] = $this->aThreadUIDs;
|
||||
}
|
||||
if ($this->aThreadUnseenUIDs) {
|
||||
$result['threadUnseen'] = $this->aThreadUnseenUIDs;
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ class MessageListParams
|
|||
$bHideDeleted = true;
|
||||
|
||||
protected int
|
||||
$iOffset,
|
||||
$iLimit,
|
||||
$iOffset = 0,
|
||||
$iLimit = 0,
|
||||
$iPrevUidNext = 0, // used to check for new messages
|
||||
$iThreadUid = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@
|
|||
<div class="flagParent fontastic"></div>
|
||||
<div class="senderParent actionHandle" data-bind="attr: {'title': senderClearEmailsString}, text: senderEmailsString"></div>
|
||||
<div class="subjectParent actionHandle" data-bind="text: subject"></div>
|
||||
<div class="threads-len" data-bind="visible: 1 < threadsLen(), text: threadsLen"></div>
|
||||
<div class="threads-len" data-bind="visible: 1 < threadsLen(), text: threadsLen, attr: {'data-unseen': threadUnseenLen() || null}"></div>
|
||||
<div class="attachmentParent actionHandle">
|
||||
<i data-bind="css: attachmentIconClass"></i>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue