Improved FolderCollection handling

This commit is contained in:
the-djmaze 2023-03-03 15:50:27 +01:00
parent a61ef0fa1c
commit 33c10365f0
10 changed files with 79 additions and 97 deletions

View file

@ -227,8 +227,6 @@ export class FolderCollectionModel extends AbstractCollectionModel
name: name,
fullName: parentName,
delimiter: delimiter,
exists: false,
isSubscribed: false,
flags: ['\\nonexistent']
});
setFolder(pfolder);
@ -380,6 +378,8 @@ export class FolderModel extends AbstractModel {
isFlagged: () => FolderUserStore.currentFolder() === this
&& MessagelistUserStore.listSearch().includes('flagged'),
// isSubscribed: () => this.flags().includes('\\subscribed'),
hasVisibleSubfolders: () => !!this.subFolders().find(folder => folder.visible()),
hasSubscriptions: () => this.isSubscribed() | !!this.subFolders().find(
@ -535,6 +535,10 @@ export class FolderModel extends AbstractModel {
path.pop();
folder.parentName = path.join(folder.delimiter);
folder.isSubscribed(folder.flags.includes('\\subscribed'));
folder.exists = !folder.flags.includes('\\nonexistent');
folder.selectable(folder.exists && !folder.flags.includes('\\noselect'));
type && 'mail' != type && folder.kolabType(type);
}
return folder;

View file

@ -476,6 +476,9 @@ html.sm-msgView-bottom {
}
}
/*
@media all and (display-mode: fullscreen) {
*/
html.rl-fullscreen {
#rl-left,

View file

@ -39,6 +39,11 @@ abstract class Collection extends \ArrayObject implements \JsonSerializable
}
}
public function keys() : array
{
return \array_keys($this->getArrayCopy());
}
public function Add($mItem, bool $bToTop = false) : self
{
$this->append($mItem, $bToTop);

View file

@ -13,6 +13,7 @@
namespace MailSo\Imap\Commands;
use MailSo\Imap\Folder;
use MailSo\Imap\FolderCollection;
use MailSo\Imap\FolderInformation;
use MailSo\Imap\SequenceSet;
use MailSo\Imap\Enumerations\FolderStatus;
@ -171,7 +172,7 @@ trait Folders
$oFolderInfo = $this->oCurrentFolderInfo;
$bReselect = false;
$bWritable = false;
if ($oFolderInfo && $sFolderName === $oFolderInfo->FolderName) {
if ($oFolderInfo && $sFolderName === $oFolderInfo->FullName) {
if ($oFolderInfo->hasStatus) {
return $oFolderInfo;
}
@ -351,7 +352,7 @@ trait Folders
{
if (!$bForceReselect
&& $this->oCurrentFolderInfo
&& $sFolderName === $this->oCurrentFolderInfo->FolderName
&& $sFolderName === $this->oCurrentFolderInfo->FullName
&& ($bIsWritable === $this->oCurrentFolderInfo->IsWritable || $this->oCurrentFolderInfo->IsWritable)
) {
return $this->oCurrentFolderInfo;
@ -444,7 +445,7 @@ trait Folders
* @throws \MailSo\Net\Exceptions\*
* @throws \MailSo\Imap\Exceptions\*
*/
public function FolderList(string $sParentFolderName, string $sListPattern, bool $bIsSubscribeList = false, bool $bUseListStatus = false) : array
public function FolderList(string $sParentFolderName, string $sListPattern, bool $bIsSubscribeList = false, bool $bUseListStatus = false) : FolderCollection
{
$sCmd = 'LIST';
@ -504,16 +505,17 @@ trait Folders
$aMetadata = $bMetadata ? $this->getAllMetadata() : null;
$this->SendRequest($sCmd, $aParameters);
$aReturn = array();
$aFolders = array();
$oFolderCollection = new FolderCollection;
$sDelimiter = '';
$bInbox = false;
foreach ($this->yieldUntaggedResponses() as $oResponse) {
if ('STATUS' === $oResponse->StatusOrIndex && isset($oResponse->ResponseList[2])) {
$sFullName = $this->toUTF8($oResponse->ResponseList[2]);
if (!isset($aReturn[$sFullName])) {
$aReturn[$sFullName] = new Folder($sFullName);
if (!isset($oFolderCollection[$sFullName])) {
$oFolderCollection[$sFullName] = new Folder($sFullName);
}
$aReturn[$sFullName]->setStatusFromResponse($oResponse);
$oFolderCollection[$sFullName]->setStatusFromResponse($oResponse);
}
else if ($sCmd === $oResponse->StatusOrIndex && 5 === \count($oResponse->ResponseList)) {
try
@ -527,18 +529,16 @@ trait Folders
* $oResponse->ResponseList[3] = Delimiter
* $oResponse->ResponseList[4] = FullName
*/
if (isset($aReturn[$sFullName])) {
$oFolder = $aReturn[$sFullName];
if (isset($oFolderCollection[$sFullName])) {
$oFolder = $oFolderCollection[$sFullName];
$oFolder->setDelimiter($oResponse->ResponseList[3]);
$oFolder->setFlags($oResponse->ResponseList[2]);
} else {
$oFolder = new Folder($sFullName, $oResponse->ResponseList[3], $oResponse->ResponseList[2]);
$aReturn[$sFullName] = $oFolder;
$oFolderCollection[$sFullName] = $oFolder;
}
if ($oFolder->IsInbox()) {
$bInbox = true;
}
$bInbox = $bInbox || $oFolder->IsInbox();
if (!$sDelimiter) {
$sDelimiter = $oFolder->Delimiter();
@ -547,8 +547,6 @@ trait Folders
if (isset($aMetadata[$oResponse->ResponseList[4]])) {
$oFolder->SetAllMetadata($aMetadata[$oResponse->ResponseList[4]]);
}
$aReturn[$sFullName] = $oFolder;
}
catch (\Throwable $oException)
{
@ -557,13 +555,16 @@ trait Folders
}
}
// $iOptimizationLimit = $this->Settings->folder_list_limit;
// $oFolderCollection->Optimized = 10 < $iOptimizationLimit && $oFolderCollection->count() > $iOptimizationLimit;
// RFC 5464
if ($bMetadata && !$aMetadata /*&& 50 < \count($aReturn)*/) {
foreach ($aReturn as $oFolder) {
// if (2 > \substr_count($oFolder->FullName(), $oFolder->Delimiter()))
if ($bMetadata && !$aMetadata /*&& 50 < $oFolderCollection->count()*/) {
foreach ($oFolderCollection as $oFolder) {
// if (2 > \substr_count($oFolder->FullName, $oFolder->Delimiter()))
try {
$oFolder->SetAllMetadata(
$this->getMetadata($oFolder->FullName(), ['/shared', '/private'], ['DEPTH'=>'infinity'])
$this->getMetadata($oFolder->FullName, ['/shared', '/private'], ['DEPTH'=>'infinity'])
);
} catch (\Throwable $oException) {
// Ignore error
@ -571,11 +572,11 @@ trait Folders
}
}
if (!$bInbox && !$sParentFolderName && !isset($aReturn['INBOX'])) {
$aReturn['INBOX'] = new Folder('INBOX', $sDelimiter);
if (!$bInbox && !$sParentFolderName && !isset($oFolderCollection['INBOX'])) {
$oFolderCollection['INBOX'] = new Folder('INBOX', $sDelimiter);
}
return $aReturn;
return $oFolderCollection;
}
/**
@ -583,7 +584,7 @@ trait Folders
* @throws \MailSo\Net\Exceptions\*
* @throws \MailSo\Imap\Exceptions\*
*/
public function FolderSubscribeList(string $sParentFolderName, string $sListPattern) : array
public function FolderSubscribeList(string $sParentFolderName, string $sListPattern) : FolderCollection
{
return $this->FolderList($sParentFolderName, $sListPattern, true);
}
@ -593,7 +594,7 @@ trait Folders
* @throws \MailSo\Net\Exceptions\*
* @throws \MailSo\Imap\Exceptions\*
*/
public function FolderStatusList(string $sParentFolderName, string $sListPattern) : array
public function FolderStatusList(string $sParentFolderName, string $sListPattern) : FolderCollection
{
return $this->FolderList($sParentFolderName, $sListPattern, false, true);
}

View file

@ -39,7 +39,7 @@ class Folder implements \JsonSerializable
if (!\strlen($sFullName)) {
throw new \InvalidArgumentException;
}
$this->FolderName = $sFullName;
$this->FullName = $sFullName;
$this->setDelimiter($sDelimiter);
$this->setFlags($aFlags);
/*
@ -68,7 +68,7 @@ class Folder implements \JsonSerializable
public function Name() : string
{
$sNameRaw = $this->FolderName;
$sNameRaw = $this->FullName;
if ($this->sDelimiter) {
$aNames = \explode($this->sDelimiter, $sNameRaw);
return \end($aNames);
@ -76,11 +76,6 @@ class Folder implements \JsonSerializable
return $sNameRaw;
}
public function FullName() : string
{
return $this->FolderName;
}
public function Delimiter() : ?string
{
return $this->sDelimiter;
@ -91,14 +86,10 @@ class Folder implements \JsonSerializable
return $this->aFlagsLowerCase;
}
public function Exists() : bool
{
return !\in_array('\\nonexistent', $this->aFlagsLowerCase);
}
public function Selectable() : bool
{
return !\in_array('\\noselect', $this->aFlagsLowerCase) && $this->Exists();
return !\in_array('\\noselect', $this->aFlagsLowerCase)
&& !\in_array('\\nonexistent', $this->aFlagsLowerCase);
}
public function IsSubscribed() : bool
@ -108,7 +99,7 @@ class Folder implements \JsonSerializable
public function IsInbox() : bool
{
return 'INBOX' === \strtoupper($this->FolderName) || \in_array('\\inbox', $this->aFlagsLowerCase);
return 'INBOX' === \strtoupper($this->FullName) || \in_array('\\inbox', $this->aFlagsLowerCase);
}
public function SetMetadata(string $sName, string $sData) : void
@ -150,7 +141,7 @@ class Folder implements \JsonSerializable
if ($match) {
$role = \array_shift($match);
}
if (!$role && 'INBOX' === \strtoupper($this->FolderName)) {
if (!$role && 'INBOX' === \strtoupper($this->FullName)) {
return 'inbox';
}
}
@ -179,17 +170,14 @@ class Folder implements \JsonSerializable
/*
if ($this->ImapClient->hasCapability('ACL') || $this->ImapClient->CapabilityValue('RIGHTS')) {
// MailSo\Imap\Responses\ACL
$rights = $this->ImapClient->FolderMyRights($this->FolderName);
$rights = $this->ImapClient->FolderMyRights($this->FullName);
}
*/
return array(
'@Object' => 'Object/Folder',
'name' => $this->Name(),
'fullName' => $this->FolderName,
'fullName' => $this->FullName,
'delimiter' => (string) $this->sDelimiter,
'isSubscribed' => $this->IsSubscribed(),
'exists' => $this->Exists(),
'selectable' => $this->Selectable(),
'flags' => $this->aFlagsLowerCase,
// 'extended' => $aExtended,
// 'permanentFlags' => $this->PermanentFlags,

View file

@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace MailSo\Mail;
namespace MailSo\Imap;
/**
* @category MailSo
@ -21,22 +21,16 @@ class FolderCollection extends \MailSo\Base\Collection
public function append($oFolder, bool $bToTop = false) : void
{
assert($oFolder instanceof \MailSo\Imap\Folder);
assert($oFolder instanceof Folder);
parent::append($oFolder, $bToTop);
}
public function FindDelimiter() : string
{
$oFolder = $this['INBOX'] ?? $this[0] ?? null;
return $oFolder ? $oFolder->Delimiter() : '/';
}
#[\ReturnTypeWillChange]
public function jsonSerialize()
{
return array(
'@Object' => 'Collection/FolderCollection',
'@Collection' => $this->getArrayCopy(),
'@Collection' => \array_values($this->getArrayCopy()),
// 'optimized' => $this->Optimized
);
}

View file

@ -33,9 +33,9 @@ class FolderInformation implements \JsonSerializable
*/
public array $PermanentFlags = array();
function __construct(string $sFolderName, bool $bIsWritable)
function __construct(string $sFullName, bool $bIsWritable)
{
$this->FolderName = $sFolderName;
$this->FullName = $sFullName;
$this->IsWritable = $bIsWritable;
}
@ -56,7 +56,7 @@ class FolderInformation implements \JsonSerializable
{
$result = array(
'id' => $this->MAILBOXID,
'name' => $this->FolderName,
'name' => $this->FullName,
'flags' => $this->Flags,
'permanentFlags' => $this->PermanentFlags,
'uidNext' => $this->UIDNEXT,

View file

@ -22,7 +22,7 @@ namespace MailSo\Imap\Traits;
*/
trait Status
{
public string $FolderName;
public string $FullName;
public bool $hasStatus = false;
@ -102,7 +102,7 @@ trait Status
return null;
}
return \md5('FolderHash/'. \implode('-', [
$this->FolderName,
$this->FullName,
$this->MESSAGES,
$this->UIDNEXT,
$this->UIDVALIDITY,

View file

@ -11,6 +11,7 @@
namespace MailSo\Mail;
use MailSo\Imap\FolderCollection;
use MailSo\Imap\FolderInformation;
use MailSo\Imap\Enumerations\FetchType;
use MailSo\Imap\Enumerations\MessageFlag;
@ -794,45 +795,32 @@ class MailClient
public function Folders(string $sParent, string $sListPattern, bool $bUseListSubscribeStatus) : ?FolderCollection
{
$aImapSubscribedFoldersHelper = null;
if ($this->oImapClient->hasCapability('LIST-EXTENDED')) {
$bUseListSubscribeStatus = false;
} else if ($bUseListSubscribeStatus) {
// $this->oImapClient->Settings->disable_list_status
$oFolderCollection = $this->oImapClient->FolderStatusList($sParent, $sListPattern);
if (!$oFolderCollection->count()) {
return null;
}
if ($bUseListSubscribeStatus && !$this->oImapClient->hasCapability('LIST-EXTENDED')) {
// $this->oLogger && $this->oLogger->Write('RFC5258 not supported, using LSUB');
// \SnappyMail\Log::warning('IMAP', 'RFC5258 not supported, using LSUB');
try
{
$aSubscribedFolders = $this->oImapClient->FolderSubscribeList($sParent, $sListPattern);
$aImapSubscribedFoldersHelper = array();
foreach ($aSubscribedFolders as /* @var $oImapFolder \MailSo\Imap\Folder */ $oImapFolder) {
$aImapSubscribedFoldersHelper[] = $oImapFolder->FullName();
$oSubscribedFolders = $this->oImapClient->FolderSubscribeList($sParent, $sListPattern);
foreach ($oSubscribedFolders as /* @var $oImapFolder \MailSo\Imap\Folder */ $oImapFolder) {
isset($oFolderCollection[$oImapFolder->FullName])
&& $oFolderCollection[$oImapFolder->FullName]->setSubscribed();
}
}
catch (\Throwable $oException)
{
\SnappyMail\Log::error('IMAP', 'FolderSubscribeList: ' . $oException->getMessage());
}
}
// $this->oImapClient->Settings->disable_list_status
$aFolders = $this->oImapClient->FolderStatusList($sParent, $sListPattern);
if (!$aFolders) {
return null;
}
if ($bUseListSubscribeStatus) {
foreach ($aFolders as $sFullName => /* @var $oImapFolder \MailSo\Imap\Folder */ $oImapFolder) {
if (null === $aImapSubscribedFoldersHelper || \in_array($sFullName, $aImapSubscribedFoldersHelper)) {
foreach ($oFolderCollection as /* @var $oImapFolder \MailSo\Imap\Folder */ $oImapFolder) {
$oImapFolder->setSubscribed();
}
}
}
$oFolderCollection = new FolderCollection;
// $iOptimizationLimit = $this->oImapClient->Settings->folder_list_limit;
// $oFolderCollection->Optimized = 10 < $iOptimizationLimit && \count($aFolders) > $iOptimizationLimit;
$oFolderCollection->exchangeArray(\array_values($aFolders));
return $oFolderCollection;
}
@ -930,23 +918,22 @@ class MailClient
throw new \InvalidArgumentException;
}
$aSubscribeFolders = array();
$oSubscribedFolders = array();
if ($bSubscribe) {
$aSubscribeFolders = $this->oImapClient->FolderSubscribeList($sPrevFolderFullName, '*');
foreach ($aSubscribeFolders as /* @var $oFolder \MailSo\Imap\Folder */ $oFolder) {
$this->oImapClient->FolderUnsubscribe($oFolder->FullName());
$oSubscribedFolders = $this->oImapClient->FolderSubscribeList($sPrevFolderFullName, '*');
foreach ($oSubscribedFolders as /* @var $oFolder \MailSo\Imap\Folder */ $oFolder) {
$this->oImapClient->FolderUnsubscribe($oFolder->FullName);
}
}
$this->oImapClient->FolderRename($sPrevFolderFullName, $sNewFolderFullName);
foreach ($aSubscribeFolders as /* @var $oFolder \MailSo\Imap\Folder */ $oFolder) {
$sFolderFullNameForResubscribe = $oFolder->FullName();
foreach ($oSubscribedFolders as /* @var $oFolder \MailSo\Imap\Folder */ $oFolder) {
$sFolderFullNameForResubscribe = $oFolder->FullName;
if (\str_starts_with($sFolderFullNameForResubscribe, $sPrevFolderFullName)) {
$sNewFolderFullNameForResubscribe = $sNewFolderFullName.
\substr($sFolderFullNameForResubscribe, \strlen($sPrevFolderFullName));
$this->oImapClient->FolderSubscribe($sNewFolderFullNameForResubscribe);
$this->oImapClient->FolderSubscribe(
$sNewFolderFullName . \substr($sFolderFullNameForResubscribe, \strlen($sPrevFolderFullName))
);
}
}

View file

@ -204,7 +204,7 @@ trait Response
);
$this->aCheckableFolder = \is_array($aCheckable) ? $aCheckable : array();
}
$aResult['checkable'] = \in_array($mResponse->FullName(), $this->aCheckableFolder);
$aResult['checkable'] = \in_array($mResponse->FullName, $this->aCheckableFolder);
return $aResult;
}
@ -216,7 +216,7 @@ trait Response
return \array_slice($mResult['@Collection'], 0, 100);
}
if ($mResponse instanceof \MailSo\Mail\AttachmentCollection
|| $mResponse instanceof \MailSo\Mail\FolderCollection
|| $mResponse instanceof \MailSo\Imap\FolderCollection
|| $mResponse instanceof \MailSo\Mail\MessageCollection
) {
return $mResult;