diff --git a/dev/Model/FolderCollection.js b/dev/Model/FolderCollection.js index e9c86ed47..7b7650f1b 100644 --- a/dev/Model/FolderCollection.js +++ b/dev/Model/FolderCollection.js @@ -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; diff --git a/dev/Styles/User/MessageView.less b/dev/Styles/User/MessageView.less index b9807ff13..8aca8ee33 100644 --- a/dev/Styles/User/MessageView.less +++ b/dev/Styles/User/MessageView.less @@ -476,6 +476,9 @@ html.sm-msgView-bottom { } } +/* +@media all and (display-mode: fullscreen) { +*/ html.rl-fullscreen { #rl-left, diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Base/Collection.php b/snappymail/v/0.0.0/app/libraries/MailSo/Base/Collection.php index 0605b89cc..634c5a3c7 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Base/Collection.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Base/Collection.php @@ -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); diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Commands/Folders.php b/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Commands/Folders.php index 16b213803..1ac4e35e4 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Commands/Folders.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Commands/Folders.php @@ -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); } diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Folder.php b/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Folder.php index 9037f36ae..4030938aa 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Folder.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Folder.php @@ -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, diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Mail/FolderCollection.php b/snappymail/v/0.0.0/app/libraries/MailSo/Imap/FolderCollection.php similarity index 70% rename from snappymail/v/0.0.0/app/libraries/MailSo/Mail/FolderCollection.php rename to snappymail/v/0.0.0/app/libraries/MailSo/Imap/FolderCollection.php index 9c6265997..8e2d9d8c2 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Mail/FolderCollection.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Imap/FolderCollection.php @@ -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 ); } diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Imap/FolderInformation.php b/snappymail/v/0.0.0/app/libraries/MailSo/Imap/FolderInformation.php index db1f902cc..5104487df 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Imap/FolderInformation.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Imap/FolderInformation.php @@ -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, diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Traits/Status.php b/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Traits/Status.php index d595d148e..1f909f3fb 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Traits/Status.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Imap/Traits/Status.php @@ -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, diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php b/snappymail/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php index 43ea10797..964c926ef 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php @@ -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)) + ); } } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Response.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Response.php index bc1e41497..9590565dd 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Response.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Response.php @@ -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;