Better mail message handling

* Cleanup HTML parsing
* Drop useless Microsoft 'Sensitivity' MIME Header
* Revamp Flags handling
This commit is contained in:
djmaze 2021-12-06 16:08:58 +01:00
parent ddbcb4bfa4
commit d734a3e415
17 changed files with 175 additions and 478 deletions

View file

@ -507,14 +507,8 @@ class AppUser extends AbstractApp {
}
if (result.Flags.length) {
result.Flags.forEach(flags =>
MessageFlagsCache.storeByFolderAndUid(folderFromCache.fullName, flags.Uid.toString(), [
!!flags.IsUnseen,
!!flags.IsFlagged,
!!flags.IsAnswered,
!!flags.IsForwarded,
!!flags.IsReadReceipt
])
result.Flags.forEach(message =>
MessageFlagsCache.storeByFolderAndUid(folderFromCache.fullName, message.Uid.toString(), message.Flags)
);
this.reloadFlagsCurrentMessageListAndMessageFromCache();

View file

@ -1,5 +1,5 @@
import { MessageSetAction } from 'Common/EnumsUser';
import { arrayLength, pInt } from 'Common/Utils';
import { isArray, pInt } from 'Common/Utils';
let FOLDERS_CACHE = {},
FOLDERS_NAME_CACHE = {},
@ -176,16 +176,8 @@ export class MessageFlagsCache
const uid = message.uid,
flags = this.getFor(message.folder, uid);
if (flags && flags.length) {
message.isFlagged(!!flags[1]);
if (!message.isSimpleMessage) {
message.isUnseen(!!flags[0]);
message.isAnswered(!!flags[2]);
message.isForwarded(!!flags[3]);
message.isReadReceipt(!!flags[4]);
message.isDeleted(!!flags[5]);
}
if (isArray(flags)) {
message.flags(flags);
}
if (message.threads.length) {
@ -216,14 +208,7 @@ export class MessageFlagsCache
*/
static store(message) {
if (message) {
this.setFor(message.folder, message.uid, [
message.isUnseen(),
message.isFlagged(),
message.isAnswered(),
message.isForwarded(),
message.isReadReceipt(),
message.isDeleted()
]);
this.setFor(message.folder, message.uid, message.flags());
}
}
@ -233,7 +218,7 @@ export class MessageFlagsCache
* @param {Array} flags
*/
static storeByFolderAndUid(folder, uid, flags) {
if (arrayLength(flags)) {
if (isArray(flags)) {
this.setFor(folder, uid, flags);
}
}
@ -245,30 +230,34 @@ export class MessageFlagsCache
*/
static storeBySetAction(folder, uid, setAction) {
let unread = 0;
const flags = this.getFor(folder, uid);
const flags = this.getFor(folder, uid),
remove = item => {
const index = flags.indexOf(item);
if (index > -1) {
flags.splice(index, 1);
}
};
if (arrayLength(flags)) {
if (flags[0]) {
unread = 1;
}
if (isArray(flags)) {
unread = flags.includes('\\seen') ? 0 : 1;
switch (setAction) {
case MessageSetAction.SetSeen:
flags[0] = false;
flags.push('\\seen');
break;
case MessageSetAction.UnsetSeen:
flags[0] = true;
remove('\\seen');
break;
case MessageSetAction.SetFlag:
flags[1] = true;
flags.push('\\flagged');
break;
case MessageSetAction.UnsetFlag:
flags[1] = false;
remove('\\flagged');
break;
// no default
}
this.setFor(folder, uid, flags);
this.setFor(folder, uid, flags.unique());
}
return unread;

View file

@ -56,12 +56,6 @@ export class MessageModel extends AbstractModel {
senderClearEmailsString: '',
deleted: false,
isDeleted: false,
isUnseen: false,
isFlagged: false,
isAnswered: false,
isForwarded: false,
isReadReceipt: false,
focused: false,
selected: false,
@ -86,11 +80,21 @@ export class MessageModel extends AbstractModel {
this.attachmentsSpecData = ko.observableArray();
this.threads = ko.observableArray();
this.unsubsribeLinks = ko.observableArray();
this.flags = ko.observableArray();
this.addComputables({
attachmentIconClass: () => FileInfo.getCombinedIconClass(this.hasAttachments() ? this.attachmentsSpecData() : []),
threadsLen: () => this.threads().length,
isImportant: () => MessagePriority.High === this.priority(),
isDeleted: () => this.flags().includes('\\deleted'),
isUnseen: () => !this.flags().includes('\\seen') /* || this.flags().includes('\\unseen')*/,
isFlagged: () => this.flags().includes('\\flagged'),
isAnswered: () => this.flags().includes('\\answered'),
isForwarded: () => this.flags().includes('$forwarded'),
isReadReceipt: () => this.flags().includes('$mdnsent')
// isJunk: () => this.flags().includes('$junk') && !this.flags().includes('$nonjunk'),
// isPhishing: () => this.flags().includes('$phishing')
});
}
@ -129,12 +133,6 @@ export class MessageModel extends AbstractModel {
this.senderClearEmailsString('');
this.deleted(false);
this.isDeleted(false);
this.isUnseen(false);
this.isFlagged(false);
this.isAnswered(false);
this.isForwarded(false);
this.isReadReceipt(false);
this.selected(false);
this.checked(false);
@ -192,8 +190,8 @@ export class MessageModel extends AbstractModel {
json.Priority = MessagePriority.Normal;
}
if (super.revivePropertiesFromJson(json)) {
// this.foundedCIDs = isArray(json.FoundedCIDs) ? json.FoundedCIDs : [];
// this.attachments(AttachmentCollectionModel.reviveFromJson(json.Attachments, this.foundedCIDs));
// this.foundCIDs = isArray(json.FoundCIDs) ? json.FoundCIDs : [];
// this.attachments(AttachmentCollectionModel.reviveFromJson(json.Attachments, this.foundCIDs));
this.computeSenderEmail();
}
@ -436,12 +434,7 @@ export class MessageModel extends AbstractModel {
this.deliveredTo = message.deliveredTo;
this.unsubsribeLinks(message.unsubsribeLinks);
this.isUnseen(message.isUnseen());
this.isFlagged(message.isFlagged());
this.isAnswered(message.isAnswered());
this.isForwarded(message.isForwarded());
this.isReadReceipt(message.isReadReceipt());
this.isDeleted(message.isDeleted());
this.flags(message.flags());
this.priority(message.priority());

View file

@ -159,8 +159,8 @@ class RemoteUserFetch extends AbstractFetchRemote {
* @param {boolean} bSetSeen
* @param {Array} aThreadUids = null
*/
messageSetSeenToAll(fCallback, sFolderFullName, bSetSeen, aThreadUids = null) {
this.request('MessageSetSeenToAll', fCallback, {
messageSetSeenToAll(sFolderFullName, bSetSeen, aThreadUids = null) {
this.request('MessageSetSeenToAll', null, {
Folder: sFolderFullName,
SetAction: bSetSeen ? 1 : 0,
ThreadUids: aThreadUids ? aThreadUids.join(',') : ''

View file

@ -453,16 +453,11 @@ export const MessageUserStore = new class {
if (message && message.uid == json.Uid) {
oMessage || this.messageError('');
/*
if (cached) {
delete json.IsSeen;
delete json.IsFlagged;
delete json.IsAnswered;
delete json.IsForwarded;
delete json.IsReadReceipt;
delete json.IsDeleted;
delete json.Flags;
}
*/
message.revivePropertiesFromJson(json);
addRequestedMessage(message.folder, message.uid);

View file

@ -452,75 +452,6 @@ export class MailMessageList extends AbstractViewRight {
rl.app.messageListAction(sFolderFullName, iSetAction, aMessages);
}
/**
* @param {string} sFolderFullName
* @param {number} iSetAction
* @param {number} iThreadUid = ''
* @returns {void}
*/
setActionForAll(sFolderFullName, iSetAction, iThreadUid = 0) {
if (sFolderFullName) {
let cnt = 0;
const uids = [];
let folder = getFolderFromCacheList(sFolderFullName);
if (folder) {
switch (iSetAction) {
case MessageSetAction.SetSeen:
MessageUserStore.list.forEach(message => {
if (message.isUnseen()) {
++cnt;
}
message.isUnseen(false);
uids.push(message.uid);
});
if (iThreadUid) {
folder.messageCountUnread(folder.messageCountUnread() - cnt);
if (0 > folder.messageCountUnread()) {
folder.messageCountUnread(0);
}
} else {
folder.messageCountUnread(0);
}
MessageFlagsCache.clearFolder(sFolderFullName);
Remote.messageSetSeenToAll(null, sFolderFullName, true, iThreadUid ? uids : null);
break;
case MessageSetAction.UnsetSeen:
MessageUserStore.list.forEach(message => {
if (!message.isUnseen()) {
++cnt;
}
message.isUnseen(true);
uids.push(message.uid);
});
if (iThreadUid) {
folder.messageCountUnread(folder.messageCountUnread() + cnt);
if (folder.messageCountAll() < folder.messageCountUnread()) {
folder.messageCountUnread(folder.messageCountAll());
}
} else {
folder.messageCountUnread(folder.messageCountAll());
}
MessageFlagsCache.clearFolder(sFolderFullName);
Remote.messageSetSeenToAll(null, sFolderFullName, false, iThreadUid ? uids : null);
break;
// no default
}
rl.app.reloadFlagsCurrentMessageListAndMessageFromCache();
}
}
}
listSetSeen() {
this.setAction(
FolderUserStore.currentFolderFullName(),
@ -530,11 +461,37 @@ export class MailMessageList extends AbstractViewRight {
}
listSetAllSeen() {
this.setActionForAll(
FolderUserStore.currentFolderFullName(),
MessageSetAction.SetSeen,
MessageUserStore.listEndThreadUid()
);
let sFolderFullName = FolderUserStore.currentFolderFullName(),
iThreadUid = MessageUserStore.listEndThreadUid();
if (sFolderFullName) {
let cnt = 0;
const uids = [];
let folder = getFolderFromCacheList(sFolderFullName);
if (folder) {
MessageUserStore.list.forEach(message => {
if (message.isUnseen()) {
++cnt;
}
message.flags.push('\\seen');
// message.flags.valueHasMutated();
uids.push(message.uid);
});
if (iThreadUid) {
folder.messageCountUnread(Math.max(0, folder.messageCountUnread() - cnt));
} else {
folder.messageCountUnread(0);
}
MessageFlagsCache.clearFolder(sFolderFullName);
Remote.messageSetSeenToAll(sFolderFullName, true, iThreadUid ? uids : null);
rl.app.reloadFlagsCurrentMessageListAndMessageFromCache();
}
}
}
listUnsetSeen() {

View file

@ -606,7 +606,8 @@ export class MailMessageView extends AbstractViewRight {
Text: i18n('READ_RECEIPT/BODY', { 'READ-RECEIPT': AccountUserStore.email() })
});
oMessage.isReadReceipt(true);
oMessage.flags.push('$mdnsent');
// oMessage.flags.valueHasMutated();
MessageFlagsCache.store(oMessage);