Improved reviveFromJson() for *Model

This commit is contained in:
djmaze
2020-10-23 15:15:54 +02:00
parent f4b2fddf5e
commit 76c4f62186
18 changed files with 226 additions and 341 deletions

View File

@@ -596,7 +596,7 @@ class AppUser extends AbstractApp {
check = true;
const flags = data.Result.Flags[uid];
storeMessageFlagsToCacheByFolderAndUid(folderFromCache.fullNameRaw, uid.toString(), [
!flags.IsSeen,
!!flags.IsUnseen,
!!flags.IsFlagged,
!!flags.IsAnswered,
!!flags.IsForwarded,

View File

@@ -198,14 +198,14 @@ export function initMessageFlagsFromCache(message) {
flags = getMessageFlagsFromCache(message.folderFullNameRaw, uid);
if (flags && flags.length) {
message.flagged(!!flags[1]);
message.isFlagged(!!flags[1]);
if (!message.isSimpleMessage) {
message.unseen(!!flags[0]);
message.answered(!!flags[2]);
message.forwarded(!!flags[3]);
message.isUnseen(!!flags[0]);
message.isAnswered(!!flags[2]);
message.isForwarded(!!flags[3]);
message.isReadReceipt(!!flags[4]);
message.deletedMark(!!flags[5]);
message.isDeleted(!!flags[5]);
}
}
@@ -238,12 +238,12 @@ export function initMessageFlagsFromCache(message) {
export function storeMessageFlagsToCache(message) {
if (message) {
setMessageFlagsToCache(message.folderFullNameRaw, message.uid, [
message.unseen(),
message.flagged(),
message.answered(),
message.forwarded(),
message.isUnseen(),
message.isFlagged(),
message.isAnswered(),
message.isForwarded(),
message.isReadReceipt(),
message.deletedMark()
message.isDeleted()
]);
}
}

View File

@@ -9,10 +9,14 @@ function typeCast(current, value) {
switch (typeof current)
{
case 'boolean': return !!value;
case 'string': return null != value ? '' + value : '';
case 'number':
value = parseInt(value, 10);
return (isNaN(value) || !isFinite(value)) ? 0 : value;
case 'number': return isFinite(value) ? parseFloat(value) : 0;
case 'string': return null != value ? '' + value : '';
case 'object':
if (current.constructor.reviveFromJson) {
return current.constructor.reviveFromJson(value) || undefined;
}
if (!Array.isArray(current) || !Array.isArray(value))
return undefined;
}
return value;
}
@@ -26,7 +30,7 @@ export class AbstractModel {
constructor() {
/*
if (new.target === AbstractModel) {
throw new Error("Can't instantiate abstract class!");
throw new Error("Can't instantiate AbstractModel!");
}
this.sModelName = new.target.name;
*/
@@ -63,34 +67,53 @@ export class AbstractModel {
*/
static reviveFromJson(json) {
let obj = this.validJson(json) ? new this() : null;
obj && obj.revivePropertiesFromJson(json);
return obj;
}
revivePropertiesFromJson(json) {
let model = this.constructor;
try {
obj && Object.entries(json).forEach(([key, value]) => {
if (!model.validJson(json)) {
return false;
}
Object.entries(json).forEach(([key, value]) => {
if ('@' !== key[0]) {
key = key[0].toLowerCase() + key.substr(1);
switch (typeof obj[key])
switch (typeof this[key])
{
case 'function':
if (ko.isObservable(obj[key]) && !ko.isObservableArray(obj[key])) {
obj[key](typeCast(obj[key](), value));
if (ko.isObservable(this[key])) {
value = typeCast(this[key](), value);
if (undefined !== value) {
this[key](value);
break;
}
// console.log((typeof this[key]())+' '+(model.name)+'.'+key+' not revived');
}
// else { console.log('('+(typeof obj[key])+') '+key+' not revived'); }
// else console.log(model.name + '.' + key + ' is a function');
break;
case 'boolean':
case 'string':
case 'number':
obj[key] = typeCast(obj[key], value);
break;
// case 'undefined':
// default:
// console.log('('+(typeof obj[key])+') '+key+' not revived');
case 'object':
case 'string':
value = typeCast(this[key], value);
if (undefined !== value) {
this[key] = value;
break;
}
// fall through
case 'undefined':
default:
// console.log((typeof this[key])+' '+(model.name)+'.'+key+' not revived');
}
}
});
} catch (e) {
console.log(this.name);
console.log(model.name);
console.error(e);
}
return obj;
return true;
}
}

View File

@@ -1,15 +1,13 @@
export class AbstractCollectionModel extends Array
{
constructor(props) {
constructor() {
/*
if (new.target === Parent) {
throw new Error("Can't instantiate abstract class!");
if (new.target === AbstractCollectionModel) {
throw new Error("Can't instantiate AbstractCollectionModel!");
}
*/
super();
props && Object.entries(props).forEach(([key, value]) => '@' !== key[0] && (this[key] = value));
// props[@Count]
}
/**
@@ -18,18 +16,22 @@ export class AbstractCollectionModel extends Array
* @returns {*CollectionModel}
*/
static reviveFromJson(json, itemCallback) {
// FolderCollectionModel => FolderCollection
// AttachmentCollectionModel => AttachmentCollection
// MessageCollectionModel => MessageCollection
if (json && 'Collection/'+this.name.replace('Model', '') === json['@Object']
&& Array.isArray(json['@Collection'])) {
const result = new this(json);
json['@Collection'].forEach(item => {
item && itemCallback && (item = itemCallback(item, result));
item && result.push(item);
});
return result;
if (json) {
const result = new this();
if ('Collection/'+this.name.replace('Model', '') === json['@Object']) {
Object.entries(json).forEach(([key, value]) => '@' !== key[0] && (result[key] = value));
// json[@Count]
json = json['@Collection'];
}
if (Array.isArray(json)) {
json.forEach(item => {
item && itemCallback && (item = itemCallback(item, result));
item && result.push(item);
});
return result;
}
}
return null;
}
}

View File

@@ -10,16 +10,7 @@ export class AttachmentCollectionModel extends AbstractCollectionModel
* @returns {AttachmentCollectionModel}
*/
static reviveFromJson(items) {
let cb = attachment => AttachmentModel.reviveFromJson(attachment),
result = super.reviveFromJson(items, cb);
if (!result) {
result = new AttachmentCollectionModel;
Array.isArray(items) && items.forEach(attachment => {
attachment = cb(attachment);
attachment && result.push(attachment);
});
}
return result;
return super.reviveFromJson(items, attachment => AttachmentModel.reviveFromJson(attachment));
}
/**

View File

@@ -10,12 +10,7 @@ export class EmailCollectionModel extends AbstractCollectionModel
* @returns {EmailCollectionModel}
*/
static reviveFromJson(items) {
let result = new EmailCollectionModel;
Array.isArray(items) && items.forEach(email => {
email = EmailModel.reviveFromJson(email);
email && result.push(email);
});
return result;
return super.reviveFromJson(items, email => EmailModel.reviveFromJson(email));
}
/**

View File

@@ -5,6 +5,7 @@ import { isPosNumeric } from 'Common/UtilsUser';
import { i18n, trigger as translatorTrigger } from 'Common/Translator';
import { AbstractModel } from 'Knoin/AbstractModel';
import { FolderCollectionModel } from 'Model/FolderCollection';
class FolderModel extends AbstractModel {
constructor() {
@@ -29,7 +30,7 @@ class FolderModel extends AbstractModel {
this.edited = ko.observable(false);
this.subScribed = ko.observable(true);
this.checkable = ko.observable(false);
this.subFolders = ko.observableArray([]);
this.subFolders = ko.observableArray(new FolderCollectionModel);
this.deleteAccess = ko.observable(false);
this.actionBlink = ko.observable(false).extend({ falseTimeout: 1000 });

View File

@@ -47,6 +47,12 @@ export class FolderCollectionModel extends AbstractCollectionModel
bDisplaySpecSetting = FolderStore.displaySpecSetting();
return super.reviveFromJson(object, (oFolder, self) => {
let oCacheFolder = Cache.getFolderFromCacheList(oFolder.FullNameRaw);
/*
if (oCacheFolder) {
oFolder.SubFolders = FolderCollectionModel.reviveFromJson(oFolder.SubFolders);
oFolder.SubFolders && oCacheFolder.subFolders(oFolder.SubFolders);
}
*/
if (!oCacheFolder && (oCacheFolder = FolderModel.reviveFromJson(oFolder))) {
if (oFolder.FullNameRaw == self.SystemFolders[ServerFolderType.INBOX]) {
oCacheFolder.type(FolderType.Inbox);
@@ -75,10 +81,6 @@ export class FolderCollectionModel extends AbstractCollectionModel
oCacheFolder.messageCountUnread(oFolder.Extended.MessageUnseenCount);
}
}
oFolder.SubFolders = FolderCollectionModel.reviveFromJson(oFolder.SubFolders);
oFolder.SubFolders && oCacheFolder.subFolders(oFolder.SubFolders);
}
return oCacheFolder;
});

View File

@@ -3,13 +3,11 @@ import ko from 'ko';
import { MessagePriority, SignedVerifyStatus } from 'Common/Enums';
import { i18n } from 'Common/Translator';
import { pInt } from 'Common/Utils';
import { encodeHtml } from 'Common/UtilsUser';
import { messageViewLink, messageDownloadLink } from 'Common/Links';
import FolderStore from 'Stores/User/Folder';
import PgpStore from 'Stores/User/Pgp';
import { File } from 'Common/File';
import { AttachmentCollectionModel } from 'Model/AttachmentCollection';
@@ -40,22 +38,17 @@ class MessageModel extends AbstractModel {
this.dateTimeStampInUTC = ko.observable(0);
this.priority = ko.observable(MessagePriority.Normal);
this.fromEmailString = ko.observable('');
this.fromClearEmailString = ko.observable('');
this.toEmailsString = ko.observable('');
this.toClearEmailsString = ko.observable('');
this.senderEmailsString = ko.observable('');
this.senderClearEmailsString = ko.observable('');
this.newForAnimation = ko.observable(false);
this.deleted = ko.observable(false);
this.deletedMark = ko.observable(false);
this.unseen = ko.observable(false);
this.flagged = ko.observable(false);
this.answered = ko.observable(false);
this.forwarded = ko.observable(false);
this.isDeleted = ko.observable(false);
this.isUnseen = ko.observable(false);
this.isFlagged = ko.observable(false);
this.isAnswered = ko.observable(false);
this.isForwarded = ko.observable(false);
this.isReadReceipt = ko.observable(false);
this.focused = ko.observable(false);
@@ -91,52 +84,12 @@ class MessageModel extends AbstractModel {
this.regDisposables([this.attachmentIconClass, this.threadsLen, this.isImportant]);
}
/**
* @static
* @param {FetchJsonMessage} json
* @returns {?MessageModel}
*/
static reviveFromJson(json) {
const oMessageModel = super.reviveFromJson(json);
if (oMessageModel) {
oMessageModel.folderFullNameRaw = json.Folder;
oMessageModel.from = EmailCollectionModel.reviveFromJson(json.From);
oMessageModel.to = EmailCollectionModel.reviveFromJson(json.To);
oMessageModel.cc = EmailCollectionModel.reviveFromJson(json.Cc);
oMessageModel.bcc = EmailCollectionModel.reviveFromJson(json.Bcc);
oMessageModel.replyTo = EmailCollectionModel.reviveFromJson(json.ReplyTo);
oMessageModel.deliveredTo = EmailCollectionModel.reviveFromJson(json.DeliveredTo);
oMessageModel.unsubsribeLinks = Array.isNotEmpty(json.UnsubsribeLinks) ? json.UnsubsribeLinks : [];
if (isArray(json.SubjectParts)) {
oMessageModel.subjectPrefix(json.SubjectParts[0]);
oMessageModel.subjectSuffix(json.SubjectParts[1]);
} else {
oMessageModel.subjectPrefix('');
oMessageModel.subjectSuffix(oMessageModel.subject());
}
oMessageModel.fromEmailString(oMessageModel.from.toString(true));
oMessageModel.fromClearEmailString(oMessageModel.from.toStringClear());
oMessageModel.toEmailsString(oMessageModel.to.toString(true));
oMessageModel.toClearEmailsString(oMessageModel.to.toStringClear());
oMessageModel.threads(isArray(json.Threads) ? json.Threads : []);
oMessageModel.setFromJson(json);
oMessageModel.initFlagsByJson(json);
oMessageModel.computeSenderEmail();
}
return oMessageModel;
}
_reset() {
this.folderFullNameRaw = '';
this.folder = '';
this.uid = '';
this.hash = '';
this.requestHash = '';
this.proxy = false;
this.externalProxy = false;
this.emails = [];
this.from = new EmailCollectionModel;
this.to = new EmailCollectionModel;
@@ -146,10 +99,10 @@ class MessageModel extends AbstractModel {
this.deliveredTo = new EmailCollectionModel;
this.unsubsribeLinks = [];
this.body = null;
this.aDraftInfo = [];
this.sMessageId = '';
this.sInReplyTo = '';
this.sReferences = '';
this.draftInfo = [];
this.messageId = '';
this.inReplyTo = '';
this.references = '';
}
clear() {
@@ -161,21 +114,17 @@ class MessageModel extends AbstractModel {
this.dateTimeStampInUTC(0);
this.priority(MessagePriority.Normal);
this.fromEmailString('');
this.fromClearEmailString('');
this.toEmailsString('');
this.toClearEmailsString('');
this.senderEmailsString('');
this.senderClearEmailsString('');
this.newForAnimation(false);
this.deleted(false);
this.deletedMark(false);
this.unseen(false);
this.flagged(false);
this.answered(false);
this.forwarded(false);
this.isDeleted(false);
this.isUnseen(false);
this.isFlagged(false);
this.isAnswered(false);
this.isForwarded(false);
this.isReadReceipt(false);
this.selected(false);
@@ -219,65 +168,34 @@ class MessageModel extends AbstractModel {
}
computeSenderEmail() {
const sentFolder = FolderStore.sentFolder(),
draftFolder = FolderStore.draftFolder();
this.senderEmailsString(
this.folderFullNameRaw === sentFolder || this.folderFullNameRaw === draftFolder
? this.toEmailsString()
: this.fromEmailString()
);
this.senderClearEmailsString(
this.folderFullNameRaw === sentFolder || this.folderFullNameRaw === draftFolder
? this.toClearEmailsString()
: this.fromClearEmailString()
);
}
setFromJson(json) {
let result = MessageModel.validJson(json);
if (result) {
let priority = pInt(json.Priority);
this.priority(
[MessagePriority.High, MessagePriority.Low].includes(priority) ? priority : MessagePriority.Normal
);
this.proxy = !!json.ExternalProxy;
this.hasAttachments(!!json.HasAttachments);
this.attachmentsSpecData(isArray(json.AttachmentsSpecData) ? json.AttachmentsSpecData : []);
}
return result;
const list = [FolderStore.sentFolder(), FolderStore.draftFolder()].includes(this.folder) ? 'to' : 'from';
this.senderEmailsString(this[list].toString(true));
this.senderClearEmailsString(this[list].toStringClear());
}
/**
* @param {FetchJsonMessage} json
* @returns {boolean}
*/
initUpdateByMessageJson(json) {
let result = this.setFromJson(json);
if (result) {
this.aDraftInfo = json.DraftInfo;
this.sMessageId = json.MessageId;
this.sInReplyTo = json.InReplyTo;
this.sReferences = json.References;
if (PgpStore.capaOpenPGP()) {
this.isPgpSigned(!!json.PgpSigned);
this.isPgpEncrypted(!!json.PgpEncrypted);
revivePropertiesFromJson(json) {
if ('Priority' in json) {
let p = parseInt(json.Priority, 10);
json.Priority = MessagePriority.High == p || MessagePriority.Low == p ? p : MessagePriority.Normal;
}
if (super.revivePropertiesFromJson(json)) {
if (isArray(json.SubjectParts)) {
this.subjectPrefix(json.SubjectParts[0]);
this.subjectSuffix(json.SubjectParts[1]);
} else {
this.subjectPrefix('');
this.subjectSuffix(this.subject());
}
// this.foundedCIDs = isArray(json.FoundedCIDs) ? json.FoundedCIDs : [];
// this.attachments(AttachmentCollectionModel.reviveFromJson(json.Attachments, this.foundedCIDs));
this.attachments(AttachmentCollectionModel.reviveFromJson(json.Attachments));
this.readReceipt(json.ReadReceipt || '');
this.computeSenderEmail();
}
return result;
}
/**
@@ -294,23 +212,6 @@ class MessageModel extends AbstractModel {
return this.unsubsribeLinks && this.unsubsribeLinks.length ? this.unsubsribeLinks[0] || '' : '';
}
/**
* @param {FetchJsonMessage} json
* @returns {boolean}
*/
initFlagsByJson(json) {
let result = MessageModel.validJson(json);
if (result) {
this.unseen(!json.IsSeen);
this.flagged(!!json.IsFlagged);
this.answered(!!json.IsAnswered);
this.forwarded(!!json.IsForwarded);
this.isReadReceipt(!!json.IsReadReceipt);
this.deletedMark(!!json.IsDeleted);
}
return result;
}
/**
* @param {boolean} friendlyView
* @param {boolean=} wrapWithLink = false
@@ -375,13 +276,13 @@ class MessageModel extends AbstractModel {
let classes = [];
Object.entries({
'deleted': this.deleted(),
'deleted-mark': this.deletedMark(),
'deleted-mark': this.isDeleted(),
'selected': this.selected(),
'checked': this.checked(),
'flagged': this.flagged(),
'unseen': this.unseen(),
'answered': this.answered(),
'forwarded': this.forwarded(),
'flagged': this.isFlagged(),
'unseen': this.isUnseen(),
'answered': this.isAnswered(),
'forwarded': this.isForwarded(),
'focused': this.focused(),
'important': this.isImportant(),
'withAttachments': this.hasAttachments(),
@@ -394,27 +295,6 @@ class MessageModel extends AbstractModel {
return classes.join(' ');
}
/**
* @returns {string}
*/
messageId() {
return this.sMessageId;
}
/**
* @returns {string}
*/
inReplyTo() {
return this.sInReplyTo;
}
/**
* @returns {string}
*/
references() {
return this.sReferences;
}
/**
* @returns {string}
*/
@@ -522,7 +402,7 @@ class MessageModel extends AbstractModel {
* @returns {string}
*/
generateUid() {
return this.folderFullNameRaw + '/' + this.uid;
return this.folder + '/' + this.uid;
}
/**
@@ -531,7 +411,7 @@ class MessageModel extends AbstractModel {
*/
populateByMessageListItem(message) {
if (message) {
this.folderFullNameRaw = message.folderFullNameRaw;
this.folder = message.folder;
this.uid = message.uid;
this.hash = message.hash;
this.requestHash = message.requestHash;
@@ -546,12 +426,7 @@ class MessageModel extends AbstractModel {
this.dateTimeStampInUTC(message.dateTimeStampInUTC());
this.priority(message.priority());
this.proxy = message.proxy;
this.fromEmailString(message.fromEmailString());
this.fromClearEmailString(message.fromClearEmailString());
this.toEmailsString(message.toEmailsString());
this.toClearEmailsString(message.toClearEmailsString());
this.externalProxy = message.externalProxy;
this.emails = message.emails;
@@ -563,12 +438,12 @@ class MessageModel extends AbstractModel {
this.deliveredTo = message.deliveredTo;
this.unsubsribeLinks = message.unsubsribeLinks;
this.unseen(message.unseen());
this.flagged(message.flagged());
this.answered(message.answered());
this.forwarded(message.forwarded());
this.isUnseen(message.isUnseen());
this.isFlagged(message.isFlagged());
this.isAnswered(message.isAnswered());
this.isForwarded(message.isForwarded());
this.isReadReceipt(message.isReadReceipt());
this.deletedMark(message.deletedMark());
this.isDeleted(message.isDeleted());
this.priority(message.priority());
@@ -580,10 +455,10 @@ class MessageModel extends AbstractModel {
this.body = null;
this.aDraftInfo = [];
this.sMessageId = '';
this.sInReplyTo = '';
this.sReferences = '';
this.draftInfo = [];
this.messageId = '';
this.inReplyTo = '';
this.references = '';
if (message) {
this.threads(message.threads());
@@ -599,7 +474,7 @@ class MessageModel extends AbstractModel {
this.hasImages(false);
this.body.rlHasImages = false;
let body = this.body, attr = this.proxy ? 'data-x-additional-src' : 'data-x-src';
let body = this.body, attr = this.externalProxy ? 'data-x-additional-src' : 'data-x-src';
body.querySelectorAll('[' + attr + ']').forEach(node => {
if (node.matches('img')) {
node.loading = 'lazy';
@@ -608,7 +483,7 @@ class MessageModel extends AbstractModel {
node.removeAttribute('data-loaded');
});
attr = this.proxy ? 'data-x-additional-style-url' : 'data-x-style-url';
attr = this.externalProxy ? 'data-x-additional-style-url' : 'data-x-style-url';
body.querySelectorAll('[' + attr + ']').forEach(node => {
node.setAttribute('style', ((node.getAttribute('style')||'')
+ ';' + node.getAttribute(attr))
@@ -691,11 +566,11 @@ class MessageModel extends AbstractModel {
flagHash() {
return [
this.deleted(),
this.deletedMark(),
this.unseen(),
this.flagged(),
this.answered(),
this.forwarded(),
this.isDeleted(),
this.isUnseen(),
this.isFlagged(),
this.isAnswered(),
this.isForwarded(),
this.isReadReceipt()
].join(',');
}

View File

@@ -38,7 +38,7 @@ export class MessageCollectionModel extends AbstractCollectionModel
return super.reviveFromJson(object, message => {
message = MessageModel.reviveFromJson(message);
if (message) {
if (hasNewMessageAndRemoveFromCache(message.folderFullNameRaw, message.uid) && 5 >= newCount) {
if (hasNewMessageAndRemoveFromCache(message.folder, message.uid) && 5 >= newCount) {
++newCount;
message.newForAnimation(true);
}

View File

@@ -432,13 +432,13 @@ class RemoteUserFetch extends AbstractFetchRemote {
if (Array.isNotEmpty(list)) {
request = false;
list.forEach(messageListItem => {
if (!getMessageFlagsFromCache(messageListItem.folderFullNameRaw, messageListItem.uid)) {
if (!getMessageFlagsFromCache(messageListItem.folder, messageListItem.uid)) {
uids.push(messageListItem.uid);
}
if (messageListItem.threads().length) {
messageListItem.threads().forEach(uid => {
if (!getMessageFlagsFromCache(messageListItem.folderFullNameRaw, uid)) {
if (!getMessageFlagsFromCache(messageListItem.folder, uid)) {
uids.push(uid);
}
});
@@ -779,28 +779,28 @@ class RemoteUserFetch extends AbstractFetchRemote {
folderDelete(sFolderFullNameRaw, fTrigger) {
return this.postRequest('FolderDelete', fTrigger, {
'Folder': sFolderFullNameRaw
Folder: sFolderFullNameRaw
});
}
folderCreate(sNewFolderName, sParentName, fTrigger) {
return this.postRequest('FolderCreate', fTrigger, {
'Folder': sNewFolderName,
'Parent': sParentName
Folder: sNewFolderName,
Parent: sParentName
});
}
folderRename(sPrevFolderFullNameRaw, sNewFolderName, fTrigger) {
return this.postRequest('FolderRename', fTrigger, {
'Folder': sPrevFolderFullNameRaw,
'NewFolderName': sNewFolderName
Folder: sPrevFolderFullNameRaw,
NewFolderName: sNewFolderName
});
}
attachmentsActions(sAction, aHashes, fTrigger) {
return this.postRequest('AttachmentsActions', fTrigger, {
'Do': sAction,
'Hashes': aHashes
Do: sAction,
Hashes: aHashes
});
}
}

View File

@@ -205,7 +205,7 @@ class MessageUserStore {
this.messageListEndFolder.subscribe(folder => {
const message = this.message();
if (message && folder && folder !== message.folderFullNameRaw) {
if (message && folder && folder !== message.folder) {
this.message(null);
}
});
@@ -295,7 +295,7 @@ class MessageUserStore {
: [];
messages.forEach(item => {
if (item && item.unseen()) {
if (item && item.isUnseen()) {
++unseenCount;
}
});
@@ -442,6 +442,7 @@ class MessageUserStore {
setMessage(data, cached) {
let isNew = false,
body = null,
json = data && data.Result,
id = '',
plain = '',
resultHtml = '',
@@ -451,14 +452,14 @@ class MessageUserStore {
message = this.message();
if (
data &&
MessageModel.validJson(data.Result) &&
json &&
MessageModel.validJson(json) &&
message &&
message.folderFullNameRaw === data.Result.Folder
message.folder === json.Folder
) {
const threads = message.threads();
if (message.uid !== data.Result.Uid && 1 < threads.length && threads.includes(data.Result.Uid)) {
message = MessageModel.reviveFromJson(data.Result);
if (message.uid !== json.Uid && 1 < threads.length && threads.includes(json.Uid)) {
message = MessageModel.reviveFromJson(json);
if (message) {
message.threads(threads);
initMessageFlagsFromCache(message);
@@ -470,16 +471,21 @@ class MessageUserStore {
}
}
if (message && message.uid === data.Result.Uid) {
if (message && message.uid === json.Uid) {
this.messageError('');
message.initUpdateByMessageJson(data.Result);
addRequestedMessage(message.folderFullNameRaw, message.uid);
if (!cached) {
message.initFlagsByJson(data.Result);
if (cached) {
delete json.IsSeen;
delete json.IsFlagged;
delete json.IsAnswered;
delete json.IsForwarded;
delete json.IsReadReceipt;
delete json.IsDeleted;
}
message.revivePropertiesFromJson(json);
addRequestedMessage(message.folder, message.uid);
if (messagesDom) {
id = 'rl-mgs-' + message.hash.replace(/[^a-zA-Z0-9]/g, '');
@@ -490,15 +496,15 @@ class MessageUserStore {
message.body = textBody;
} else {
let isHtml = false;
if (data.Result.Html) {
if (json.Html) {
isHtml = true;
resultHtml = data.Result.Html.toString();
} else if (data.Result.Plain) {
resultHtml = json.Html.toString();
} else if (json.Plain) {
isHtml = false;
resultHtml = plainToHtml(data.Result.Plain.toString());
resultHtml = plainToHtml(json.Plain.toString());
if ((message.isPgpSigned() || message.isPgpEncrypted()) && PgpStore.capaOpenPGP()) {
plain = pString(data.Result.Plain);
plain = pString(json.Plain);
const isPgpEncrypted = /---BEGIN PGP MESSAGE---/.test(plain);
if (!isPgpEncrypted) {
@@ -544,13 +550,13 @@ class MessageUserStore {
message.body = body;
message.isHtml(!!isHtml);
message.hasImages(!!data.Result.HasExternals);
message.hasImages(!!json.HasExternals);
messagesDom.append(body);
message.storeDataInDom();
if (data.Result.HasInternals) {
if (json.HasInternals) {
message.showInternalImages();
}
@@ -575,8 +581,8 @@ class MessageUserStore {
}
initMessageFlagsFromCache(message);
if (message.unseen() || message.hasUnseenSubMessage()) {
rl.app.messageListAction(message.folderFullNameRaw, MessageSetAction.SetSeen, [message]);
if (message.isUnseen() || message.hasUnseenSubMessage()) {
rl.app.messageListAction(message.folder, MessageSetAction.SetSeen, [message]);
}
if (isNew) {
@@ -585,7 +591,7 @@ class MessageUserStore {
if (
selectedMessage &&
message &&
(message.folderFullNameRaw !== selectedMessage.folderFullNameRaw || message.uid !== selectedMessage.uid)
(message.folder !== selectedMessage.folder || message.uid !== selectedMessage.uid)
) {
this.selectorMessageSelected(null);
if (1 === this.messageList().length) {
@@ -595,7 +601,7 @@ class MessageUserStore {
selectedMessage = this.messageList().find(
subMessage =>
subMessage &&
subMessage.folderFullNameRaw === message.folderFullNameRaw &&
subMessage.folder === message.folder &&
subMessage.uid === message.uid
);
@@ -621,7 +627,7 @@ class MessageUserStore {
selectMessageByFolderAndUid(sFolder, sUid) {
if (sFolder && sUid) {
this.message(this.staticMessage.populateByMessageListItem(null));
this.message().folderFullNameRaw = sFolder;
this.message().folder = sFolder;
this.message().uid = sUid;
this.populateMessageBody(this.message());
@@ -631,10 +637,8 @@ class MessageUserStore {
}
populateMessageBody(oMessage) {
if (oMessage) {
if (Remote.message(this.onMessageResponse, oMessage.folderFullNameRaw, oMessage.uid)) {
this.messageCurrentLoading(true);
}
if (oMessage && Remote.message(this.onMessageResponse, oMessage.folder, oMessage.uid)) {
this.messageCurrentLoading(true);
}
}

View File

@@ -643,7 +643,7 @@ class ComposePopupView extends AbstractViewNext {
if (this.bFromDraft) {
const message = MessageStore.message();
if (message && this.draftFolder() === message.folderFullNameRaw && this.draftUid() === message.uid) {
if (message && this.draftFolder() === message.folder && this.draftUid() === message.uid) {
MessageStore.message(null);
}
}
@@ -905,7 +905,7 @@ class ComposePopupView extends AbstractViewNext {
this.to(this.emailArrayToStringLineHelper(message.replyEmails(excludeEmail)));
this.subject(replySubjectAdd('Re', sSubject));
this.prepareMessageAttachments(message, lineComposeType);
this.aDraftInfo = ['reply', message.uid, message.folderFullNameRaw];
this.aDraftInfo = ['reply', message.uid, message.folder];
this.sInReplyTo = message.sMessageId;
this.sReferences = (this.sInReplyTo + ' ' + message.sReferences).trim();
break;
@@ -916,15 +916,15 @@ class ComposePopupView extends AbstractViewNext {
this.cc(this.emailArrayToStringLineHelper(resplyAllParts[1]));
this.subject(replySubjectAdd('Re', sSubject));
this.prepareMessageAttachments(message, lineComposeType);
this.aDraftInfo = ['reply', message.uid, message.folderFullNameRaw];
this.aDraftInfo = ['reply', message.uid, message.folder];
this.sInReplyTo = message.sMessageId;
this.sReferences = (this.sInReplyTo + ' ' + message.references()).trim();
this.sReferences = (this.sInReplyTo + ' ' + message.references).trim();
break;
case ComposeType.Forward:
this.subject(replySubjectAdd('Fwd', sSubject));
this.prepareMessageAttachments(message, lineComposeType);
this.aDraftInfo = ['forward', message.uid, message.folderFullNameRaw];
this.aDraftInfo = ['forward', message.uid, message.folder];
this.sInReplyTo = message.sMessageId;
this.sReferences = (this.sInReplyTo + ' ' + message.sReferences).trim();
break;
@@ -932,7 +932,7 @@ class ComposePopupView extends AbstractViewNext {
case ComposeType.ForwardAsAttachment:
this.subject(replySubjectAdd('Fwd', sSubject));
this.prepareMessageAttachments(message, lineComposeType);
this.aDraftInfo = ['forward', message.uid, message.folderFullNameRaw];
this.aDraftInfo = ['forward', message.uid, message.folder];
this.sInReplyTo = message.sMessageId;
this.sReferences = (this.sInReplyTo + ' ' + message.sReferences).trim();
break;
@@ -945,7 +945,7 @@ class ComposePopupView extends AbstractViewNext {
this.bFromDraft = true;
this.draftFolder(message.folderFullNameRaw);
this.draftFolder(message.folder);
this.draftUid(message.uid);
this.subject(sSubject);

View File

@@ -230,7 +230,7 @@ class MessageListMailBoxUserView extends AbstractViewNext {
const sFolder = e.detail.Folder, sUid = e.detail.Uid;
const message = this.messageList().find(
item => item && sFolder === item.folderFullNameRaw && sUid === item.uid
item => item && sFolder === item.folder && sUid === item.uid
);
if ('INBOX' === sFolder) {
@@ -503,11 +503,11 @@ class MessageListMailBoxUserView extends AbstractViewNext {
folder = getFolderFromCacheList(sFolderFullNameRaw);
if (folder) {
MessageStore.messageList().forEach(message => {
if (message.unseen()) {
if (message.isUnseen()) {
++cnt;
}
message.unseen(false);
message.isUnseen(false);
uids.push(message.uid);
});
@@ -529,11 +529,11 @@ class MessageListMailBoxUserView extends AbstractViewNext {
folder = getFolderFromCacheList(sFolderFullNameRaw);
if (folder) {
MessageStore.messageList().forEach(message => {
if (!message.unseen()) {
if (!message.isUnseen()) {
++cnt;
}
message.unseen(true);
message.isUnseen(true);
uids.push(message.uid);
});
@@ -605,14 +605,14 @@ class MessageListMailBoxUserView extends AbstractViewNext {
const checkedUids = checked.map(message => message.uid);
if (checkedUids.includes(currentMessage.uid)) {
this.setAction(
currentMessage.folderFullNameRaw,
currentMessage.flagged() ? MessageSetAction.UnsetFlag : MessageSetAction.SetFlag,
currentMessage.folder,
currentMessage.isFlagged() ? MessageSetAction.UnsetFlag : MessageSetAction.SetFlag,
checked
);
} else {
this.setAction(
currentMessage.folderFullNameRaw,
currentMessage.flagged() ? MessageSetAction.UnsetFlag : MessageSetAction.SetFlag,
currentMessage.folder,
currentMessage.isFlagged() ? MessageSetAction.UnsetFlag : MessageSetAction.SetFlag,
[currentMessage]
);
}
@@ -623,15 +623,15 @@ class MessageListMailBoxUserView extends AbstractViewNext {
const checked = this.messageListCheckedOrSelected();
if (checked.length) {
if (undefined === bFlag) {
const flagged = checked.filter(message => message.flagged());
const flagged = checked.filter(message => message.isFlagged());
this.setAction(
checked[0].folderFullNameRaw,
checked[0].folder,
checked.length === flagged.length ? MessageSetAction.UnsetFlag : MessageSetAction.SetFlag,
checked
);
} else {
this.setAction(
checked[0].folderFullNameRaw,
checked[0].folder,
!bFlag ? MessageSetAction.UnsetFlag : MessageSetAction.SetFlag,
checked
);
@@ -643,15 +643,15 @@ class MessageListMailBoxUserView extends AbstractViewNext {
const checked = this.messageListCheckedOrSelected();
if (checked.length) {
if (undefined === seen) {
const unseen = checked.filter(message => message.unseen());
const unseen = checked.filter(message => message.isUnseen());
this.setAction(
checked[0].folderFullNameRaw,
checked[0].folder,
unseen.length ? MessageSetAction.SetSeen : MessageSetAction.UnsetSeen,
checked
);
} else {
this.setAction(
checked[0].folderFullNameRaw,
checked[0].folder,
seen ? MessageSetAction.SetSeen : MessageSetAction.UnsetSeen,
checked
);
@@ -875,12 +875,12 @@ class MessageListMailBoxUserView extends AbstractViewNext {
prefetchNextTick() {
if (ifvisible && !this.bPrefetch && !ifvisible.now() && this.viewModelVisible) {
const message = this.messageList().find(
item => item && !hasRequestedMessage(item.folderFullNameRaw, item.uid)
item => item && !hasRequestedMessage(item.folder, item.uid)
);
if (message) {
this.bPrefetch = true;
addRequestedMessage(message.folderFullNameRaw, message.uid);
addRequestedMessage(message.folder, message.uid);
Remote.message(
(result, data) => {
@@ -890,7 +890,7 @@ class MessageListMailBoxUserView extends AbstractViewNext {
next && this.prefetchNextTick();
}, 1000);
},
message.folderFullNameRaw,
message.folder,
message.uid
);
}

View File

@@ -60,7 +60,7 @@ class MessageViewMailBoxUserView extends AbstractViewNext {
const message = this.message();
if (message && this.allowMessageListActions) {
this.message(null);
rl.app.deleteMessagesFromFolder(folderType, message.folderFullNameRaw, [message.uid], useFolder);
rl.app.deleteMessagesFromFolder(folderType, message.folder, [message.uid], useFolder);
}
}, this.messageVisibility);
@@ -226,7 +226,7 @@ class MessageViewMailBoxUserView extends AbstractViewNext {
this.scrollMessageToTop();
}
this.viewFolder = message.folderFullNameRaw;
this.viewFolder = message.folder;
this.viewUid = message.uid;
this.viewHash = message.hash;
this.viewSubject(message.subject());
@@ -245,7 +245,7 @@ class MessageViewMailBoxUserView extends AbstractViewNext {
this.viewUnsubscribeLink(message.getFirstUnsubsribeLink());
this.viewDownloadLink(message.downloadLink());
this.viewIsImportant(message.isImportant());
this.viewIsFlagged(message.flagged());
this.viewIsFlagged(message.isFlagged());
} else {
this.viewFolder = '';
this.viewUid = '';
@@ -257,7 +257,7 @@ class MessageViewMailBoxUserView extends AbstractViewNext {
this.message.viewTrigger.subscribe(() => {
const message = this.message();
message ? this.viewIsFlagged(message.flagged()) : this.viewIsFlagged(false);
message ? this.viewIsFlagged(message.isFlagged()) : this.viewIsFlagged(false);
});
this.fullScreenMode.subscribe(value => $htmlCL.toggle('rl-message-fullscreen', value));
@@ -467,8 +467,8 @@ class MessageViewMailBoxUserView extends AbstractViewNext {
// eslint-disable-line prefer-arrow-callback
const message = this.message();
message && rl.app.messageListAction(
message.folderFullNameRaw,
message.flagged() ? MessageSetAction.UnsetFlag : MessageSetAction.SetFlag,
message.folder,
message.isFlagged() ? MessageSetAction.UnsetFlag : MessageSetAction.SetFlag,
[message]
);
}
@@ -479,7 +479,7 @@ class MessageViewMailBoxUserView extends AbstractViewNext {
const message = ko.dataFor(el); // eslint-disable-line no-invalid-this
message && message.folder && message.uid && rl.app.messageListAction(
message.folder,
message.flagged() ? MessageSetAction.UnsetFlag : MessageSetAction.SetFlag,
message.isFlagged() ? MessageSetAction.UnsetFlag : MessageSetAction.SetFlag,
[message]
);
@@ -639,21 +639,21 @@ class MessageViewMailBoxUserView extends AbstractViewNext {
* @returns {boolean}
*/
isDraftFolder() {
return MessageStore.message() && FolderStore.draftFolder() === MessageStore.message().folderFullNameRaw;
return MessageStore.message() && FolderStore.draftFolder() === MessageStore.message().folder;
}
/**
* @returns {boolean}
*/
isSentFolder() {
return MessageStore.message() && FolderStore.sentFolder() === MessageStore.message().folderFullNameRaw;
return MessageStore.message() && FolderStore.sentFolder() === MessageStore.message().folder;
}
/**
* @returns {boolean}
*/
isSpamFolder() {
return MessageStore.message() && FolderStore.spamFolder() === MessageStore.message().folderFullNameRaw;
return MessageStore.message() && FolderStore.spamFolder() === MessageStore.message().folder;
}
/**
@@ -667,7 +667,7 @@ class MessageViewMailBoxUserView extends AbstractViewNext {
* @returns {boolean}
*/
isArchiveFolder() {
return MessageStore.message() && FolderStore.archiveFolder() === MessageStore.message().folderFullNameRaw;
return MessageStore.message() && FolderStore.archiveFolder() === MessageStore.message().folder;
}
/**
@@ -762,7 +762,7 @@ class MessageViewMailBoxUserView extends AbstractViewNext {
if (oMessage && oMessage.readReceipt()) {
Remote.sendReadReceiptMessage(
()=>{},
oMessage.folderFullNameRaw,
oMessage.folder,
oMessage.uid,
oMessage.readReceipt(),
i18n('READ_RECEIPT/SUBJECT', { 'SUBJECT': oMessage.subject() }),

View File

@@ -255,12 +255,12 @@ class Message implements \JsonSerializable
return $this->sPgpSignature;
}
public function PgpSigned() : bool
public function isPgpSigned() : bool
{
return $this->bPgpSigned;
}
public function PgpEncrypted() : bool
public function isPgpEncrypted() : bool
{
return $this->bPgpEncrypted;
}
@@ -420,11 +420,6 @@ class Message implements \JsonSerializable
$this->aThreads = $aThreads;
}
public function TextPartIsTrimmed() : bool
{
return $this->bTextPartIsTrimmed;
}
public static function NewFetchResponseInstance(string $sFolder, \MailSo\Imap\FetchResponse $oFetchResponse, ?\MailSo\Imap\BodyStructure $oBodyStructure = null) : self
{
return (new self)->InitByFetchResponse($sFolder, $oFetchResponse, $oBodyStructure);
@@ -771,13 +766,13 @@ class Message implements \JsonSerializable
'Threads' => $this->Threads(),
'Sensitivity' => $this->Sensitivity(),
'UnsubsribeLinks' => $this->UnsubsribeLinks(),
'ExternalProxy' => false,
'ReadReceipt' => '',
'HasAttachments' => $oAttachments ? 0 < $oAttachments->Count() : false,
'AttachmentsSpecData' => $oAttachments ? $oAttachments->SpecData() : array(),
// Flags
'IsUnseen' => \in_array('\\unseen', $aFlags) || !\in_array('\\seen', $aFlags),
'IsSeen' => \in_array('\\seen', $aFlags),
'IsFlagged' => \in_array('\\flagged', $aFlags),
'IsAnswered' => \in_array('\\answered', $aFlags),

View File

@@ -372,6 +372,7 @@ trait Folders
{
$aLowerFlags = array_map('strtolower', $aFlags);
$aInboxInformation['Flags'][$iUid] = array(
'IsUnseen' => \in_array('\\unseen', $aLowerFlags) || !\in_array('\\seen', $aLowerFlags),
'IsSeen' => in_array('\\seen', $aLowerFlags),
'IsFlagged' => in_array('\\flagged', $aLowerFlags),
'IsAnswered' => in_array('\\answered', $aLowerFlags),

View File

@@ -195,6 +195,11 @@ trait Response
{
if (!($mResponse instanceof \JsonSerializable))
{
if (\is_object($mResponse))
{
return '["'.\get_class($mResponse).'"]';
}
if (\is_array($mResponse))
{
foreach ($mResponse as $iKey => $oItem)
@@ -203,11 +208,6 @@ trait Response
}
}
if (\is_object($mResponse))
{
return '["'.\get_class($mResponse).'"]';
}
return $mResponse;
}
@@ -256,8 +256,6 @@ trait Response
$mResult['IsReadReceipt'] = true;
}
$mResult['TextPartIsTrimmed'] = false;
if ('Message' === $sParent)
{
$oAttachments = /* @var \MailSo\Mail\AttachmentCollection */ $mResponse->Attachments();
@@ -323,10 +321,8 @@ trait Response
$mResult['TextHash'] = \md5($mResult['Html'].$mResult['Plain']);
$mResult['TextPartIsTrimmed'] = $mResponse->TextPartIsTrimmed();
$mResult['PgpSigned'] = $mResponse->PgpSigned();
$mResult['PgpEncrypted'] = $mResponse->PgpEncrypted();
$mResult['isPgpSigned'] = $mResponse->isPgpSigned();
$mResult['isPgpEncrypted'] = $mResponse->isPgpEncrypted();
$mResult['PgpSignature'] = $mResponse->PgpSignature();
unset($sHtml, $sPlain);