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

@ -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);
}