From 4fb359be59f1d6ffb1cc6f5f09d6f544a5d6c3ec Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Mon, 20 Feb 2023 10:49:22 +0100 Subject: [PATCH] Improved messages cache handling and fixed broken messagesBodiesDom --- dev/Common/UtilsUser.js | 128 +++++++++--------- dev/Model/Message.js | 68 +++++----- dev/Settings/User/General.js | 11 +- dev/Stores/User/Message.js | 22 ++- dev/View/User/MailBox/MessageView.js | 5 +- dev/View/User/SystemDropDown.js | 5 +- .../templates/Views/User/MailMessageView.html | 20 +-- 7 files changed, 124 insertions(+), 135 deletions(-) diff --git a/dev/Common/UtilsUser.js b/dev/Common/UtilsUser.js index 1621f1b8b..a4187aefd 100644 --- a/dev/Common/UtilsUser.js +++ b/dev/Common/UtilsUser.js @@ -5,7 +5,6 @@ import { doc, createElement, elementById, dropdowns, dropdownVisibility, Setting import { plainToHtml } from 'Common/Html'; import { getNotification } from 'Common/Translator'; import { EmailCollectionModel } from 'Model/EmailCollection'; -import { MessageModel } from 'Model/Message'; import { MessageUserStore } from 'Stores/User/Message'; import { MessagelistUserStore } from 'Stores/User/Messagelist'; import { SettingsUserStore } from 'Stores/User/Settings'; @@ -246,75 +245,80 @@ setLayoutResizer = (source, sClientSideKeyName, mode) => } }, +viewMessage = (oMessage, popup) => { + if (popup) { + oMessage.viewPopupMessage(); + } else { + MessageUserStore.error(''); + let id = 'rl-msg-' + oMessage.hash, + body = oMessage.body || elementById(id); + if (!body) { + body = createElement('div',{ + id:id, + hidden:'', + class:'b-text-part' + + (oMessage.pgpSigned() ? ' openpgp-signed' : '') + + (oMessage.pgpEncrypted() ? ' openpgp-encrypted' : '') + }); + MessageUserStore.purgeCache(); + } + + body.message = oMessage; + oMessage.body = body; + + if (!SettingsUserStore.viewHTML() || !oMessage.viewHtml()) { + oMessage.viewPlain(); + } + + MessageUserStore.bodiesDom().append(body); + + MessageUserStore.loading(false); + oMessage.body.hidden = false; + + if (oMessage.isUnseen()) { + MessageUserStore.MessageSeenTimer = setTimeout( + () => MessagelistUserStore.setAction(oMessage.folder, MessageSetAction.SetSeen, [oMessage]), + SettingsUserStore.messageReadDelay() * 1000 // seconds + ); + } + } +}, + populateMessageBody = (oMessage, popup) => { if (oMessage) { popup || MessageUserStore.message(oMessage); - popup || MessageUserStore.loading(true); - Remote.message((iError, oData/*, bCached*/) => { - if (iError) { - if (Notification.RequestAborted !== iError && !popup) { - MessageUserStore.message(null); - MessageUserStore.error(getNotification(iError)); - } - } else { - let json = oData?.Result; - if (json - && MessageModel.validJson(json) - && oMessage.hash === json.hash -// && oMessage.folder === json.folder -// && oMessage.uid == json.uid - && oMessage.revivePropertiesFromJson(json) - ) { + if (oMessage.body) { + viewMessage(oMessage, popup); + } else { + popup || MessageUserStore.loading(true); + Remote.message((iError, oData/*, bCached*/) => { + if (iError) { + if (Notification.RequestAborted !== iError && !popup) { + MessageUserStore.message(null); + MessageUserStore.error(getNotification(iError)); + } + } else { + let json = oData?.Result; + if (json + && oMessage.hash === json.hash +// && oMessage.folder === json.folder +// && oMessage.uid == json.uid + && oMessage.revivePropertiesFromJson(json) + ) { /* - if (bCached) { - delete json.flags; - } -*/ - if (popup) { - oMessage.viewPopupMessage(); - } else { - MessageUserStore.error(''); - const messagesDom = MessageUserStore.bodiesDom(); - if (messagesDom) { - let id = 'rl-msg-' + oMessage.hash, - body = elementById(id); - if (body) { - oMessage.body = body; - oMessage.isHtml(body.classList.contains('html')); - oMessage.hasImages(body.rlHasImages); - } else { - body = createElement('div',{ - id:id, - hidden:'', - class:'b-text-part' - + (oMessage.pgpSigned() ? ' openpgp-signed' : '') - + (oMessage.pgpEncrypted() ? ' openpgp-encrypted' : '') - }); - oMessage.body = body; - if (!SettingsUserStore.viewHTML() || !oMessage.viewHtml()) { - oMessage.viewPlain(); - } - - MessageUserStore.purgeMessageBodyCache(); - } - - messagesDom.append(body); - - oMessage.body.hidden = false; + if (bCached) { + delete json.flags; } - } + oMessage.body.remove(); +*/ + viewMessage(oMessage, popup); - MessageFlagsCache.initMessage(oMessage); - if (oMessage.isUnseen()) { - MessageUserStore.MessageSeenTimer = setTimeout( - () => MessagelistUserStore.setAction(oMessage.folder, MessageSetAction.SetSeen, [oMessage]), - SettingsUserStore.messageReadDelay() * 1000 // seconds - ); + MessageFlagsCache.initMessage(oMessage); } } - } - popup || MessageUserStore.loading(false); - }, oMessage.folder, oMessage.uid); + popup || MessageUserStore.loading(false); + }, oMessage.folder, oMessage.uid); + } } }; diff --git a/dev/Model/Message.js b/dev/Model/Message.js index 0d62b73bc..8e9db97c1 100644 --- a/dev/Model/Message.js +++ b/dev/Model/Message.js @@ -290,49 +290,46 @@ export class MessageModel extends AbstractModel { return [[...toResult.values()], [...ccResult.values()]]; } - viewHtml() { + viewBody(html) { const body = this.body; - if (body && this.html()) { - let result = msgHtml(this); - this.hasExternals(result.hasExternals); - this.hasImages(body.rlHasImages = !!result.hasExternals); - - body.innerHTML = result.html; - - body.classList.toggle('html', 1); - body.classList.toggle('plain', 0); - - if (!this.isSpam() && FolderUserStore.spamFolder() != this.folder) { - if ('always' === SettingsUserStore.viewImages()) { - this.showExternalImages(); - } - if ('match' === SettingsUserStore.viewImages()) { - this.showExternalImages(1); + if (body) { + if (html) { + let result = msgHtml(this); + this.hasExternals(result.hasExternals); + this.hasImages(!!result.hasExternals); + body.innerHTML = result.html; + if (!this.isSpam() && FolderUserStore.spamFolder() != this.folder) { + if ('always' === SettingsUserStore.viewImages()) { + this.showExternalImages(); + } + if ('match' === SettingsUserStore.viewImages()) { + this.showExternalImages(1); + } } + } else { + body.innerHTML = plainToHtml( + (this.plain() + ? this.plain() + .replace(/-----BEGIN PGP (SIGNED MESSAGE-----(\r?\n[a-z][^\r\n]+)+|SIGNATURE-----[\s\S]*)/, '') + .trim() + : htmlToPlain(body.innerHTML) + ) + ); + this.hasImages(false); } - - this.isHtml(true); + body.classList.toggle('html', html); + body.classList.toggle('plain', !html); + this.isHtml(html); return true; } } + viewHtml() { + return this.html() && this.viewBody(true); + } + viewPlain() { - const body = this.body; - if (body) { - body.classList.toggle('html', 0); - body.classList.toggle('plain', 1); - body.innerHTML = plainToHtml( - (this.plain() - ? this.plain() - .replace(/-----BEGIN PGP (SIGNED MESSAGE-----(\r?\n[a-z][^\r\n]+)+|SIGNATURE-----[\s\S]*)/, '') - .trim() - : htmlToPlain(body.innerHTML) - ) - ); - this.isHtml(false); - this.hasImages(false); - return true; - } + return this.viewBody(false); } viewPopupMessage(print) { @@ -447,7 +444,6 @@ export class MessageModel extends AbstractModel { }); this.hasImages(hasImages); - body.rlHasImages = hasImages; } } diff --git a/dev/Settings/User/General.js b/dev/Settings/User/General.js index b4e613ea9..95f72d8a3 100644 --- a/dev/Settings/User/General.js +++ b/dev/Settings/User/General.js @@ -17,7 +17,6 @@ import { LanguageStore } from 'Stores/Language'; import { SettingsUserStore } from 'Stores/User/Settings'; import { IdentityUserStore } from 'Stores/User/Identity'; import { NotificationUserStore } from 'Stores/User/Notification'; -import { MessageUserStore } from 'Stores/User/Message'; import { MessagelistUserStore } from 'Stores/User/Messagelist'; import Remote from 'Remote/User/Fetch'; @@ -102,7 +101,7 @@ export class UserSettingsGeneral extends AbstractViewSettings { this.addSetting('Layout'); this.addSetting('MaxBlockquotesLevel'); - this.addSettings(['ViewHTML', 'ViewImages', 'ViewImagesWhitelist', 'HideDeleted', 'AllowStyles', + this.addSettings(['ViewHTML', 'ViewImages', 'ViewImagesWhitelist', 'HideDeleted', 'RemoveColors', 'AllowStyles', 'ListInlineAttachments', 'simpleAttachmentsList', 'UseCheckboxesInList', 'listGrouped', 'ReplySameFolder', 'requestReadReceipt', 'requestDsn', 'requireTLS', 'pgpSign', 'pgpEncrypt', 'allowSpellcheck', 'DesktopNotifications', 'SoundNotification', 'CollapseBlockquotes', 'AllowDraftAutosave']); @@ -123,14 +122,6 @@ export class UserSettingsGeneral extends AbstractViewSettings { hourCycle: value => Remote.saveSetting('hourCycle', value), - removeColors: value => { - let dom = MessageUserStore.bodiesDom(); - if (dom) { - dom.innerHTML = ''; - } - Remote.saveSetting('RemoveColors', value); - }, - notificationSound: value => { Remote.saveSetting('NotificationSound', value); Settings.set('NotificationSound', value); diff --git a/dev/Stores/User/Message.js b/dev/Stores/User/Message.js index e9345936b..a2376c4a6 100644 --- a/dev/Stores/User/Message.js +++ b/dev/Stores/User/Message.js @@ -30,25 +30,21 @@ export const MessageUserStore = new class { AppUserStore.focusedState(Scope.MessageList); exitFullscreen(); } - this.hideMessageBodies(); + [...(this.bodiesDom()?.children || [])].forEach(el => el.hidden = true); }, }); - this.purgeMessageBodyCache = this.purgeMessageBodyCache.throttle(30000); + this.purgeCache = this.purgeCache.throttle(30000); } - purgeMessageBodyCache() { - const messagesDom = this.bodiesDom(), - children = messagesDom?.children; - if (children) { - while (15 < children.length) { - children[0].remove(); + purgeCache(all) { + const children = this.bodiesDom()?.children || []; + let i = Math.max(0, children.length - (all ? 0 : 15)); + while (i--) { + children[i].remove(); + if (children[i].message) { + children[i].message.body = null; } } } - - hideMessageBodies() { - const messagesDom = this.bodiesDom(); - messagesDom && Array.from(messagesDom.children).forEach(el => el.hidden = true); - } }; diff --git a/dev/View/User/MailBox/MessageView.js b/dev/View/User/MailBox/MessageView.js index 10fa06b4e..fcf7df6ad 100644 --- a/dev/View/User/MailBox/MessageView.js +++ b/dev/View/User/MailBox/MessageView.js @@ -128,7 +128,6 @@ export class MailMessageView extends AbstractViewRight { this.message = currentMessage; this.messageLoadingThrottle = MessageUserStore.loading; - this.messagesBodiesDom = MessageUserStore.bodiesDom; this.messageError = MessageUserStore.error; this.fullScreenMode = isFullscreen; @@ -166,7 +165,7 @@ export class MailMessageView extends AbstractViewRight { listAttachments: () => currentMessage()?.attachments() .filter(item => SettingsUserStore.listInlineAttachments() || !item.isLinked()), - hasAttachments: () => this.listAttachments().length, + hasAttachments: () => this.listAttachments()?.length, canBeRepliedOrForwarded: () => !MessagelistUserStore.isDraftFolder() && this.messageVisibility(), @@ -459,6 +458,8 @@ export class MailMessageView extends AbstractViewRight { } return false; }); + + MessageUserStore.bodiesDom(dom.querySelector('.bodyText')); } scrollMessageToTop() { diff --git a/dev/View/User/SystemDropDown.js b/dev/View/User/SystemDropDown.js index e847df172..ff0d7d306 100644 --- a/dev/View/User/SystemDropDown.js +++ b/dev/View/User/SystemDropDown.js @@ -70,9 +70,8 @@ export class SystemDropDownUserView extends AbstractViewRight { /* // Not working yet forEachObjectEntry(oData.Result, (key, value) => rl.settings.set(key, value)); clearCache(); -// MessageUserStore.setMessage(); -// MessageUserStore.purgeMessageBodyCache(); -// MessageUserStore.hideMessageBodies(); +// MessageUserStore.message(); +// MessageUserStore.purgeCache(); MessagelistUserStore([]); // FolderUserStore.folderList([]); loadFolders(value => { diff --git a/snappymail/v/0.0.0/app/templates/Views/User/MailMessageView.html b/snappymail/v/0.0.0/app/templates/Views/User/MailMessageView.html index c65f8f7e4..d08666d40 100644 --- a/snappymail/v/0.0.0/app/templates/Views/User/MailMessageView.html +++ b/snappymail/v/0.0.0/app/templates/Views/User/MailMessageView.html @@ -30,8 +30,7 @@
- -
+
🖉
@@ -121,7 +120,7 @@
-
+
@@ -176,7 +175,7 @@
-
+
@@ -223,7 +222,7 @@
-
+
@@ -294,19 +293,22 @@
-
+ +
-
+ + +
+ -
+
-