mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-13 03:27:39 +03:00
Prevent folder/messages flags conflict by using the right name attributes for Folders
This commit is contained in:
parent
17b1deb95b
commit
f8b794ec1c
7 changed files with 48 additions and 49 deletions
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue