Prevent folder/messages flags conflict by using the right name attributes for Folders

This commit is contained in:
the-djmaze 2023-03-13 11:49:40 +01:00
parent 17b1deb95b
commit f8b794ec1c
7 changed files with 48 additions and 49 deletions

View file

@ -169,22 +169,22 @@ export class FolderCollectionModel extends AbstractCollectionModel
break; break;
} }
// Flags // Flags
if (oFolder.flags.includes('\\sentmail')) { if (oFolder.attributes.includes('\\sentmail')) {
role = 'sent'; role = 'sent';
} }
if (oFolder.flags.includes('\\spam')) { if (oFolder.attributes.includes('\\spam')) {
role = 'junk'; role = 'junk';
} }
if (oFolder.flags.includes('\\bin')) { if (oFolder.attributes.includes('\\bin')) {
role = 'trash'; role = 'trash';
} }
if (oFolder.flags.includes('\\important')) { if (oFolder.attributes.includes('\\important')) {
role = 'important'; role = 'important';
} }
if (oFolder.flags.includes('\\starred')) { if (oFolder.attributes.includes('\\starred')) {
role = 'flagged'; role = 'flagged';
} }
if (oFolder.flags.includes('\\all') || oFolder.flags.includes('\\allmail')) { if (oFolder.attributes.includes('\\all') || oFolder.flags.includes('\\allmail')) {
role = 'all'; role = 'all';
} }
} }
@ -228,7 +228,7 @@ export class FolderCollectionModel extends AbstractCollectionModel
name: name, name: name,
fullName: parentName, fullName: parentName,
delimiter: delimiter, delimiter: delimiter,
flags: ['\\nonexistent'] attributes: ['\\nonexistent']
}); });
setFolder(pfolder); setFolder(pfolder);
result.splice(i, 0, pfolder); result.splice(i, 0, pfolder);
@ -330,7 +330,8 @@ export class FolderModel extends AbstractModel {
tagsAllowed: false tagsAllowed: false
}); });
this.flags = ko.observableArray(); this.attributes = ko.observableArray();
// For messages
this.permanentFlags = ko.observableArray(); this.permanentFlags = ko.observableArray();
this.addSubscribables({ this.addSubscribables({
@ -379,7 +380,7 @@ export class FolderModel extends AbstractModel {
isFlagged: () => FolderUserStore.currentFolder() === this isFlagged: () => FolderUserStore.currentFolder() === this
&& MessagelistUserStore.listSearch().includes('flagged'), && MessagelistUserStore.listSearch().includes('flagged'),
// isSubscribed: () => this.flags().includes('\\subscribed'), // isSubscribed: () => this.attributes().includes('\\subscribed'),
hasVisibleSubfolders: () => !!this.subFolders().find(folder => folder.visible()), hasVisibleSubfolders: () => !!this.subFolders().find(folder => folder.visible()),
@ -536,9 +537,9 @@ export class FolderModel extends AbstractModel {
path.pop(); path.pop();
folder.parentName = path.join(folder.delimiter); folder.parentName = path.join(folder.delimiter);
folder.isSubscribed(folder.flags.includes('\\subscribed')); folder.isSubscribed(folder.attributes.includes('\\subscribed'));
folder.exists = !folder.flags.includes('\\nonexistent'); folder.exists = !folder.attributes.includes('\\nonexistent');
folder.selectable(folder.exists && !folder.flags.includes('\\noselect')); folder.selectable(folder.exists && !folder.attributes.includes('\\noselect'));
type && 'mail' != type && folder.kolabType(type); type && 'mail' != type && folder.kolabType(type);
} }

View file

@ -85,7 +85,7 @@ export class UserSettingsFolders /*extends AbstractViewSettings*/ {
folder: folderToRemove.fullName folder: folderToRemove.fullName
}).then( }).then(
() => { () => {
// folderToRemove.flags.push('\\nonexistent'); // folderToRemove.attributes.push('\\nonexistent');
folderToRemove.selectable(false); folderToRemove.selectable(false);
// folderToRemove.isSubscribed(false); // folderToRemove.isSubscribed(false);
// folderToRemove.checkable(false); // folderToRemove.checkable(false);

View file

@ -223,8 +223,7 @@ MessagelistUserStore.reload = (bDropPagePosition = false, bDropCurrentFolderCach
folder.unreadEmails(folderInfo.unreadEmails); folder.unreadEmails(folderInfo.unreadEmails);
} }
folder.flags(folderInfo.flags); let flags = folderInfo.permanentFlags || [];
let flags = folderInfo.permanentFlags;
if (flags.includes('\\*')) { if (flags.includes('\\*')) {
let i = 6; let i = 6;
while (--i) { while (--i) {

View file

@ -9,9 +9,9 @@ class MailboxDetectPlugin extends \RainLoop\Plugins\AbstractPlugin
NAME = 'MailboxDetect', NAME = 'MailboxDetect',
AUTHOR = 'SnappyMail', AUTHOR = 'SnappyMail',
URL = 'https://snappymail.eu/', URL = 'https://snappymail.eu/',
VERSION = '2.5', VERSION = '2.6',
RELEASE = '2023-02-21', RELEASE = '2023-03-13',
REQUIRED = '2.26.3', REQUIRED = '2.27.0',
CATEGORY = 'General', CATEGORY = 'General',
LICENSE = 'MIT', LICENSE = 'MIT',
DESCRIPTION = 'Autodetect system folders and/or create them when needed'; DESCRIPTION = 'Autodetect system folders and/or create them when needed';
@ -74,13 +74,13 @@ class MailboxDetectPlugin extends \RainLoop\Plugins\AbstractPlugin
$sDelimiter || ($sDelimiter = $folder['delimiter']); $sDelimiter || ($sDelimiter = $folder['delimiter']);
if ($folder['role']) { if ($folder['role']) {
$roles[$folder['role']] = true; $roles[$folder['role']] = true;
} else if (\in_array('\\sentmail', $folder['flags'])) { } else if (\in_array('\\sentmail', $folder['attributes'])) {
$found['sent'][] = $i; $found['sent'][] = $i;
} else if (\in_array('\\spam', $folder['flags'])) { } else if (\in_array('\\spam', $folder['attributes'])) {
$found['junk'][] = $i; $found['junk'][] = $i;
} else if (\in_array('\\bin', $folder['flags'])) { } else if (\in_array('\\bin', $folder['attributes'])) {
$found['trash'][] = $i; $found['trash'][] = $i;
} else if (\in_array('\\starred', $folder['flags'])) { } else if (\in_array('\\starred', $folder['attributes'])) {
$found['flagged'][] = $i; $found['flagged'][] = $i;
} else { } else {
// Kolab // Kolab

View file

@ -424,7 +424,8 @@ trait Folders
else if (\count($oResponse->ResponseList) > 2 else if (\count($oResponse->ResponseList) > 2
&& 'FLAGS' === $oResponse->ResponseList[1] && 'FLAGS' === $oResponse->ResponseList[1]
&& \is_array($oResponse->ResponseList[2])) { && \is_array($oResponse->ResponseList[2])) {
$oResult->Flags = \array_map('\\MailSo\\Base\\Utils::Utf7ModifiedToUtf8', $oResponse->ResponseList[2]); // These could be not permanent, so we don't use them
// $oResult->Flags = \array_map('\\MailSo\\Base\\Utils::Utf7ModifiedToUtf8', $oResponse->ResponseList[2]);
} }
} }
} }
@ -529,14 +530,14 @@ trait Folders
/** /**
* $oResponse->ResponseList[0] = * * $oResponse->ResponseList[0] = *
* $oResponse->ResponseList[1] = LIST (all) | LSUB (subscribed) * $oResponse->ResponseList[1] = LIST (all) | LSUB (subscribed)
* $oResponse->ResponseList[2] = Flags * $oResponse->ResponseList[2] = Attribute flags
* $oResponse->ResponseList[3] = Delimiter * $oResponse->ResponseList[3] = Delimiter
* $oResponse->ResponseList[4] = FullName * $oResponse->ResponseList[4] = FullName
*/ */
if (isset($oFolderCollection[$sFullName])) { if (isset($oFolderCollection[$sFullName])) {
$oFolder = $oFolderCollection[$sFullName]; $oFolder = $oFolderCollection[$sFullName];
$oFolder->setDelimiter($oResponse->ResponseList[3]); $oFolder->setDelimiter($oResponse->ResponseList[3]);
$oFolder->setFlags($oResponse->ResponseList[2]); $oFolder->setAttributes($oResponse->ResponseList[2]);
} else { } else {
$oFolder = new Folder($sFullName, $oResponse->ResponseList[3], $oResponse->ResponseList[2]); $oFolder = new Folder($sFullName, $oResponse->ResponseList[3], $oResponse->ResponseList[2]);
$oFolderCollection[$sFullName] = $oFolder; $oFolderCollection[$sFullName] = $oFolder;

View file

@ -24,7 +24,7 @@ class Folder implements \JsonSerializable
private ?string $sDelimiter; private ?string $sDelimiter;
private array $aFlagsLowerCase; private array $aAttributes;
/** /**
* RFC 5464 * RFC 5464
@ -34,31 +34,31 @@ class Folder implements \JsonSerializable
/** /**
* @throws \InvalidArgumentException * @throws \InvalidArgumentException
*/ */
function __construct(string $sFullName, string $sDelimiter = null, array $aFlags = array()) function __construct(string $sFullName, string $sDelimiter = null, array $aAttributes = array())
{ {
if (!\strlen($sFullName)) { if (!\strlen($sFullName)) {
throw new \InvalidArgumentException; throw new \InvalidArgumentException;
} }
$this->FullName = $sFullName; $this->FullName = $sFullName;
$this->setDelimiter($sDelimiter); $this->setDelimiter($sDelimiter);
$this->setFlags($aFlags); $this->setAttributes($aAttributes);
/* /*
// RFC 5738 // RFC 5738
if (\in_array('\\noutf8', $this->aFlagsLowerCase)) { if (\in_array('\\noutf8', $this->aAttributes)) {
} }
if (\in_array('\\utf8only', $this->aFlagsLowerCase)) { if (\in_array('\\utf8only', $this->aAttributes)) {
} }
*/ */
} }
public function setFlags(array $aFlags) : void public function setAttributes(array $aAttributes) : void
{ {
$this->aFlagsLowerCase = \array_map('mb_strtolower', $aFlags); $this->aAttributes = \array_map('mb_strtolower', $aAttributes);
} }
public function setSubscribed() : void public function setSubscribed() : void
{ {
$this->aFlagsLowerCase = \array_unique(\array_merge($this->aFlagsLowerCase, ['\\subscribed'])); $this->aAttributes = \array_unique(\array_merge($this->aAttributes, ['\\subscribed']));
} }
public function setDelimiter(?string $sDelimiter) : void public function setDelimiter(?string $sDelimiter) : void
@ -81,25 +81,20 @@ class Folder implements \JsonSerializable
return $this->sDelimiter; return $this->sDelimiter;
} }
public function FlagsLowerCase() : array
{
return $this->aFlagsLowerCase;
}
public function Selectable() : bool public function Selectable() : bool
{ {
return !\in_array('\\noselect', $this->aFlagsLowerCase) return !\in_array('\\noselect', $this->aAttributes)
&& !\in_array('\\nonexistent', $this->aFlagsLowerCase); && !\in_array('\\nonexistent', $this->aAttributes);
} }
public function IsSubscribed() : bool public function IsSubscribed() : bool
{ {
return \in_array('\\subscribed', $this->aFlagsLowerCase); return \in_array('\\subscribed', $this->aAttributes);
} }
public function IsInbox() : bool public function IsInbox() : bool
{ {
return 'INBOX' === \strtoupper($this->FullName) || \in_array('\\inbox', $this->aFlagsLowerCase); return 'INBOX' === \strtoupper($this->FullName) || \in_array('\\inbox', $this->aAttributes);
} }
public function SetMetadata(string $sName, string $sData) : void public function SetMetadata(string $sName, string $sData) : void
@ -137,7 +132,7 @@ class Folder implements \JsonSerializable
'\\junk', // '\\spam' '\\junk', // '\\spam'
'\\sent', // '\\sentmail' '\\sent', // '\\sentmail'
'\\trash', // '\\bin' '\\trash', // '\\bin'
], $this->aFlagsLowerCase); ], $this->aAttributes);
if ($match) { if ($match) {
$role = \array_shift($match); $role = \array_shift($match);
} }
@ -162,9 +157,7 @@ class Folder implements \JsonSerializable
'name' => $this->Name(), 'name' => $this->Name(),
'fullName' => $this->FullName, 'fullName' => $this->FullName,
'delimiter' => (string) $this->sDelimiter, 'delimiter' => (string) $this->sDelimiter,
'flags' => $this->aFlagsLowerCase, 'attributes' => $this->aAttributes,
// 'extended' => $aExtended,
// 'permanentFlags' => $this->PermanentFlags,
'metadata' => $this->aMetadata, 'metadata' => $this->aMetadata,
'uidNext' => $this->UIDNEXT, 'uidNext' => $this->UIDNEXT,
// https://datatracker.ietf.org/doc/html/rfc8621#section-2 // https://datatracker.ietf.org/doc/html/rfc8621#section-2

View file

@ -23,11 +23,14 @@ class FolderInformation implements \JsonSerializable
/** /**
* Message flags * Message flags
* https://www.rfc-editor.org/rfc/rfc3501#section-7.2.6
* These could be not permanent so we don't use them
*/ */
public array $Flags = array(); public array $Flags = array();
/** /**
* NOTE: Empty when FolderExamine is used * NOTE: Empty when FolderExamine is used
* https://www.rfc-editor.org/rfc/rfc3501#page-64
*/ */
public array $PermanentFlags = array(); public array $PermanentFlags = array();
@ -39,9 +42,9 @@ class FolderInformation implements \JsonSerializable
public function IsFlagSupported(string $sFlag) : bool public function IsFlagSupported(string $sFlag) : bool
{ {
return \in_array('\\*', $this->PermanentFlags) || return \in_array('\\*', $this->PermanentFlags)
\in_array($sFlag, $this->PermanentFlags) || || \in_array($sFlag, $this->PermanentFlags);
\in_array($sFlag, $this->Flags); // || \in_array($sFlag, $this->Flags);
} }
#[\ReturnTypeWillChange] #[\ReturnTypeWillChange]
@ -69,9 +72,11 @@ class FolderInformation implements \JsonSerializable
if ($this->etag) { if ($this->etag) {
$result['etag'] = $this->etag; $result['etag'] = $this->etag;
} }
/*
if ($this->Flags) { if ($this->Flags) {
$result['flags'] = $this->Flags; $result['flags'] = $this->Flags;
} }
*/
if ($this->PermanentFlags) { if ($this->PermanentFlags) {
$result['permanentFlags'] = $this->PermanentFlags; $result['permanentFlags'] = $this->PermanentFlags;
} }