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

View file

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

View file

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

View file

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

View file

@ -424,7 +424,8 @@ trait Folders
else if (\count($oResponse->ResponseList) > 2
&& 'FLAGS' === $oResponse->ResponseList[1]
&& \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[1] = LIST (all) | LSUB (subscribed)
* $oResponse->ResponseList[2] = Flags
* $oResponse->ResponseList[2] = Attribute flags
* $oResponse->ResponseList[3] = Delimiter
* $oResponse->ResponseList[4] = FullName
*/
if (isset($oFolderCollection[$sFullName])) {
$oFolder = $oFolderCollection[$sFullName];
$oFolder->setDelimiter($oResponse->ResponseList[3]);
$oFolder->setFlags($oResponse->ResponseList[2]);
$oFolder->setAttributes($oResponse->ResponseList[2]);
} else {
$oFolder = new Folder($sFullName, $oResponse->ResponseList[3], $oResponse->ResponseList[2]);
$oFolderCollection[$sFullName] = $oFolder;

View file

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

View file

@ -23,11 +23,14 @@ class FolderInformation implements \JsonSerializable
/**
* 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();
/**
* NOTE: Empty when FolderExamine is used
* https://www.rfc-editor.org/rfc/rfc3501#page-64
*/
public array $PermanentFlags = array();
@ -39,9 +42,9 @@ class FolderInformation implements \JsonSerializable
public function IsFlagSupported(string $sFlag) : bool
{
return \in_array('\\*', $this->PermanentFlags) ||
\in_array($sFlag, $this->PermanentFlags) ||
\in_array($sFlag, $this->Flags);
return \in_array('\\*', $this->PermanentFlags)
|| \in_array($sFlag, $this->PermanentFlags);
// || \in_array($sFlag, $this->Flags);
}
#[\ReturnTypeWillChange]
@ -69,9 +72,11 @@ class FolderInformation implements \JsonSerializable
if ($this->etag) {
$result['etag'] = $this->etag;
}
/*
if ($this->Flags) {
$result['flags'] = $this->Flags;
}
*/
if ($this->PermanentFlags) {
$result['permanentFlags'] = $this->PermanentFlags;
}