mirror of
https://github.com/the-djmaze/snappymail.git
synced 2024-09-20 15:45:55 +08:00
Cleanup JavaScript MessageModel by moving dynamic code to MailMessageView and ComposePopupView
This commit is contained in:
parent
ae1de36ee0
commit
bad33e6dc4
|
@ -25,7 +25,7 @@ import { LanguageStore } from 'Stores/Language';
|
|||
import Remote from 'Remote/User/Fetch';
|
||||
|
||||
const
|
||||
hcont = Element.fromHTML('<div area="hidden" style="position:absolute;left:-5000px"></div>'),
|
||||
hcont = Element.fromHTML('<div area="hidden" style="position:absolute;left:-200vw;width:max(50vw,400px)"></div>'),
|
||||
getRealHeight = el => {
|
||||
hcont.innerHTML = el.outerHTML;
|
||||
const result = hcont.clientHeight;
|
||||
|
@ -133,22 +133,12 @@ export class MessageModel extends AbstractModel {
|
|||
attachmentIconClass: () =>
|
||||
this.encrypted() ? 'icon-lock' : FileInfo.getAttachmentsIconClass(this.attachments()),
|
||||
threadsLen: () => this.threads().length,
|
||||
listAttachments: () => this.attachments()
|
||||
.filter(item => SettingsUserStore.listInlineAttachments() || !item.isLinked()),
|
||||
hasAttachments: () => this.listAttachments().length,
|
||||
|
||||
isUnseen: () => !this.flags().includes('\\seen'),
|
||||
isFlagged: () => this.flags().includes('\\flagged'),
|
||||
isReadReceipt: () => this.flags().includes('$mdnsent'),
|
||||
// isJunk: () => this.flags().includes('$junk') && !this.flags().includes('$nonjunk'),
|
||||
// isPhishing: () => this.flags().includes('$phishing'),
|
||||
|
||||
tagsToHTML: () => this.flags().map(value =>
|
||||
isAllowedKeyword(value)
|
||||
? '<span class="focused msgflag-'+value+'">' + i18n('MESSAGE_TAGS/'+value,0,value) + '</span>'
|
||||
: ''
|
||||
).join(' '),
|
||||
|
||||
tagOptions: () => {
|
||||
const tagOptions = [];
|
||||
FolderUserStore.currentFolder().permanentFlags.forEach(value => {
|
||||
|
@ -209,61 +199,6 @@ export class MessageModel extends AbstractModel {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {boolean}
|
||||
*/
|
||||
hasUnsubsribeLinks() {
|
||||
return this.unsubsribeLinks().length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string}
|
||||
*/
|
||||
getFirstUnsubsribeLink() {
|
||||
return this.unsubsribeLinks()[0] || '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {boolean} friendlyView
|
||||
* @param {boolean=} wrapWithLink
|
||||
* @returns {string}
|
||||
*/
|
||||
fromToLine(friendlyView, wrapWithLink) {
|
||||
return this.from.toString(friendlyView, wrapWithLink);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {boolean} friendlyView
|
||||
* @param {boolean=} wrapWithLink
|
||||
* @returns {string}
|
||||
*/
|
||||
toToLine(friendlyView, wrapWithLink) {
|
||||
return this.to.toString(friendlyView, wrapWithLink);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {boolean} friendlyView
|
||||
* @param {boolean=} wrapWithLink
|
||||
* @returns {string}
|
||||
*/
|
||||
ccToLine(friendlyView, wrapWithLink) {
|
||||
return this.cc.toString(friendlyView, wrapWithLink);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string}
|
||||
*/
|
||||
bccToLine() {
|
||||
return this.bcc.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string}
|
||||
*/
|
||||
replyToToLine() {
|
||||
return this.replyTo.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
|
@ -288,7 +223,7 @@ export class MessageModel extends AbstractModel {
|
|||
/**
|
||||
* @returns {string}
|
||||
*/
|
||||
viewLink() {
|
||||
viewRaw() {
|
||||
return serverRequestRaw('ViewAsPlain', this.requestHash);
|
||||
}
|
||||
|
||||
|
@ -390,7 +325,7 @@ export class MessageModel extends AbstractModel {
|
|||
|
||||
viewPopupMessage(print) {
|
||||
const timeStampInUTC = this.dateTimeStampInUTC() || 0,
|
||||
ccLine = this.ccToLine(),
|
||||
ccLine = this.cc.toString(),
|
||||
m = 0 < timeStampInUTC ? new Date(timeStampInUTC * 1000) : null,
|
||||
win = open(''),
|
||||
sdoc = win.document;
|
||||
|
@ -402,7 +337,7 @@ export class MessageModel extends AbstractModel {
|
|||
sdoc.write(PreviewHTML
|
||||
.replace('<title>', '<title>'+subject)
|
||||
// eslint-disable-next-line max-len
|
||||
.replace('<body>', `<body style="background-color:${prop('background-color')};color:${prop('color')}"><header><h1>${subject}</h1><time>${encodeHtml(m ? m.format('LLL',0,LanguageStore.hourCycle()) : '')}</time><div>${encodeHtml(this.fromToLine())}</div><div>${encodeHtml(i18n('GLOBAL/TO'))}: ${encodeHtml(this.toToLine())}</div>${cc}</header><${mode}>${this.bodyAsHTML()}</${mode}>`)
|
||||
.replace('<body>', `<body style="background-color:${prop('background-color')};color:${prop('color')}"><header><h1>${subject}</h1><time>${encodeHtml(m ? m.format('LLL',0,LanguageStore.hourCycle()) : '')}</time><div>${encodeHtml(this.from)}</div><div>${encodeHtml(i18n('GLOBAL/TO'))}: ${encodeHtml(this.to)}</div>${cc}</header><${mode}>${this.bodyAsHTML()}</${mode}>`)
|
||||
);
|
||||
sdoc.close();
|
||||
|
||||
|
@ -435,7 +370,6 @@ export class MessageModel extends AbstractModel {
|
|||
*/
|
||||
static fromMessageListItem(message) {
|
||||
let self = new MessageModel();
|
||||
|
||||
if (message) {
|
||||
// Clone message values
|
||||
forEachObjectEntry(message, (key, value) => {
|
||||
|
@ -445,10 +379,8 @@ export class MessageModel extends AbstractModel {
|
|||
self[key] = value;
|
||||
}
|
||||
});
|
||||
self.computeSenderEmail();
|
||||
}
|
||||
|
||||
self.computeSenderEmail();
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
|
|
@ -900,7 +900,7 @@ export class ComposePopupView extends AbstractViewPopup {
|
|||
switch (msgComposeType) {
|
||||
case ComposeType.Reply:
|
||||
case ComposeType.ReplyAll:
|
||||
sFrom = message.fromToLine(false, true);
|
||||
sFrom = message.from.toString(false, true);
|
||||
sText = '<br><br><p>' + i18n('COMPOSE/REPLY_MESSAGE_TITLE', { DATETIME: sDate, EMAIL: sFrom })
|
||||
+ ':</p><blockquote>'
|
||||
+ sText.trim()
|
||||
|
@ -908,9 +908,9 @@ export class ComposePopupView extends AbstractViewPopup {
|
|||
break;
|
||||
|
||||
case ComposeType.Forward:
|
||||
sFrom = message.fromToLine(false, true);
|
||||
sTo = message.toToLine(false, true);
|
||||
sCc = message.ccToLine(false, true);
|
||||
sFrom = message.from.toString(false, true);
|
||||
sTo = message.to.toString(false, true);
|
||||
sCc = message.cc.toString(false, true);
|
||||
sText = '<br><br><p>' + i18n('COMPOSE/FORWARD_MESSAGE_TOP_TITLE') + '</p><div>'
|
||||
+ i18n('GLOBAL/FROM') + ': ' + sFrom
|
||||
+ '<br>'
|
||||
|
|
|
@ -130,7 +130,7 @@ export class MailMessageView extends AbstractViewRight {
|
|||
this.isDraftFolder = MessagelistUserStore.isDraftFolder;
|
||||
this.isSpamFolder = MessagelistUserStore.isSpamFolder;
|
||||
|
||||
this.message = MessageUserStore.message;
|
||||
this.message = currentMessage;
|
||||
this.messageLoadingThrottle = MessageUserStore.loading;
|
||||
this.messagesBodiesDom = MessageUserStore.bodiesDom;
|
||||
this.messageError = MessageUserStore.error;
|
||||
|
@ -157,6 +157,21 @@ export class MailMessageView extends AbstractViewRight {
|
|||
|
||||
messageVisibility: () => !MessageUserStore.loading() && !!currentMessage(),
|
||||
|
||||
tagsToHTML: () => currentMessage()?.flags().map(value =>
|
||||
isAllowedKeyword(value)
|
||||
? '<span class="focused msgflag-'+value+'">' + i18n('MESSAGE_TAGS/'+value,0,value) + '</span>'
|
||||
: ''
|
||||
).join(' '),
|
||||
|
||||
askReadReceipt: () =>
|
||||
(MessagelistUserStore.isDraftFolder() || MessagelistUserStore.isSentFolder())
|
||||
&& currentMessage()?.readReceipt()
|
||||
&& currentMessage()?.flags().includes('$mdnsent'),
|
||||
|
||||
listAttachments: () => currentMessage()?.attachments()
|
||||
.filter(item => SettingsUserStore.listInlineAttachments() || !item.isLinked()),
|
||||
hasAttachments: () => this.listAttachments().length,
|
||||
|
||||
canBeRepliedOrForwarded: () => !MessagelistUserStore.isDraftFolder() && this.messageVisibility(),
|
||||
|
||||
viewFromDkimVisibility: () => 'none' !== this.viewFromDkimData()[0],
|
||||
|
@ -181,6 +196,8 @@ export class MailMessageView extends AbstractViewRight {
|
|||
return '';
|
||||
},
|
||||
|
||||
firstUnsubsribeLink: () => currentMessage()?.unsubsribeLinks()[0] || '',
|
||||
|
||||
pgpSupported: () => currentMessage() && PgpUserStore.isSupported(),
|
||||
|
||||
messageListOrViewLoading:
|
||||
|
@ -195,11 +212,11 @@ export class MailMessageView extends AbstractViewRight {
|
|||
}
|
||||
this.viewHash = message.hash;
|
||||
// TODO: make first param a user setting #683
|
||||
this.viewFromShort(message.fromToLine(false, true));
|
||||
this.viewFromShort(message.from.toString(false, true));
|
||||
let dkim = 1 === arrayLength(message.from) && message.dkim
|
||||
&& message.dkim.find(dkim => message.from[0].email.includes(dkim[1]));
|
||||
this.viewFromDkimData(dkim ? [dkim[0], dkim[2]] : ['none', '']);
|
||||
this.viewToShort(message.toToLine(true, true));
|
||||
this.viewToShort(message.to.toString(true, true));
|
||||
} else {
|
||||
MessagelistUserStore.selectedMessage(null);
|
||||
|
||||
|
@ -453,13 +470,6 @@ export class MailMessageView extends AbstractViewRight {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isDraftOrSentFolder() {
|
||||
return MessagelistUserStore.isDraftFolder() || MessagelistUserStore.isSentFolder();
|
||||
}
|
||||
|
||||
scrollMessageToTop() {
|
||||
oMessageScrollerDom().scrollTop = (50 < oMessageScrollerDom().scrollTop) ? 50 : 0;
|
||||
}
|
||||
|
|
|
@ -86,8 +86,8 @@
|
|||
<li role="presentation">
|
||||
<a href="#" tabindex="-1" data-bind="command: deleteWithoutMoveCommand" data-icon="🗑" data-i18n="MESSAGE_LIST/BUTTON_DELETE_WITHOUT_MOVE"></a>
|
||||
</li>
|
||||
<li class="dividerbar" role="presentation" data-bind="visible: message().hasUnsubsribeLinks()">
|
||||
<a target="_blank" href="#" tabindex="-1" data-bind="attr: { href: message().getFirstUnsubsribeLink() }" data-icon="✖" data-i18n="MESSAGE/BUTTON_UNSUBSCRIBE"></a>
|
||||
<li class="dividerbar" role="presentation" data-bind="visible: firstUnsubsribeLink">
|
||||
<a target="_blank" href="#" tabindex="-1" data-bind="attr: { href: firstUnsubsribeLink }" data-icon="✖" data-i18n="MESSAGE/BUTTON_UNSUBSCRIBE"></a>
|
||||
</li>
|
||||
</div>
|
||||
<div data-bind="visible: allowMessageActions, with: message" class="dividerbar">
|
||||
|
@ -110,7 +110,7 @@
|
|||
<a href="#" tabindex="-1" data-bind="click: viewPlain" data-icon="👁" data-i18n="MESSAGE/PLAIN_VIEW"></a>
|
||||
</li>
|
||||
<li class="dividerbar" role="presentation">
|
||||
<a target="_blank" href="#" tabindex="-1" data-bind="attr: { href: viewLink() }">
|
||||
<a target="_blank" href="#" tabindex="-1" data-bind="attr: { href: viewRaw() }">
|
||||
<i class="icon-file-code"></i>
|
||||
<span data-i18n="MESSAGE/MENU_VIEW_ORIGINAL"></span>
|
||||
</a>
|
||||
|
@ -128,36 +128,36 @@
|
|||
<div class="subjectParent">
|
||||
<span class="infoParent g-ui-user-select-none fontastic" data-bind="click: toggleFullInfo">ℹ</span>
|
||||
<span class="flagParent g-ui-user-select-none flagOff fontastic" data-bind="text: message().isFlagged() ? '★' : '☆', css: {'flagOn': message().isFlagged(), 'flagOff': !message().isFlagged()}"></span>
|
||||
<span class="subject" data-bind="text: message().subject, title: message().subject"></span>
|
||||
<span class="subject" data-bind="text: message().subject"></span>
|
||||
<a href="#" class="close" data-bind="click: closeMessage" style="margin-top: -8px;">×</a>
|
||||
</div>
|
||||
<div class="informationShort" data-bind="hidden: showFullInfo">
|
||||
<span class="from" data-bind="html: viewFromShort, title: message().fromToLine()"></span>
|
||||
<span class="from" data-bind="html: viewFromShort, title: message().from"></span>
|
||||
<i data-bind="visible: viewFromDkimVisibility, css: viewFromDkimStatusIconClass, title: viewFromDkimStatusTitle"></i>
|
||||
</div>
|
||||
<div class="informationFull" data-bind="visible: showFullInfo, with: message">
|
||||
<table>
|
||||
<tr data-bind="visible: fromToLine()">
|
||||
<tr data-bind="visible: from.length">
|
||||
<td data-i18n="GLOBAL/FROM"></td>
|
||||
<td><span data-bind="text: fromToLine()"></span>
|
||||
<td><span data-bind="text: from"></span>
|
||||
<i data-bind="visible: $parent.viewFromDkimVisibility, css: $parent.viewFromDkimStatusIconClass, title: $parent.viewFromDkimStatusTitle"></i>
|
||||
</td>
|
||||
</tr>
|
||||
<tr data-bind="visible: toToLine()">
|
||||
<tr data-bind="visible: to.length">
|
||||
<td data-i18n="GLOBAL/TO"></td>
|
||||
<td data-bind="text: toToLine(), title: toToLine()"></td>
|
||||
<td data-bind="text: to"></td>
|
||||
</tr>
|
||||
<tr data-bind="visible: ccToLine()">
|
||||
<tr data-bind="visible: cc.length">
|
||||
<td data-i18n="GLOBAL/CC"></td>
|
||||
<td data-bind="text: ccToLine(), title: ccToLine()"></td>
|
||||
<td data-bind="text: cc"></td>
|
||||
</tr>
|
||||
<tr data-bind="visible: bccToLine()">
|
||||
<tr data-bind="visible: bcc.length">
|
||||
<td data-i18n="GLOBAL/BCC"></td>
|
||||
<td data-bind="text: bccToLine(), title: bccToLine()"></td>
|
||||
<td data-bind="text: bcc"></td>
|
||||
</tr>
|
||||
<tr data-bind="visible: replyToToLine()">
|
||||
<tr data-bind="visible: replyTo.length">
|
||||
<td data-i18n="GLOBAL/REPLY_TO"></td>
|
||||
<td data-bind="text: replyToToLine(), title: replyToToLine()"></td>
|
||||
<td data-bind="text: replyTo"></td>
|
||||
</tr>
|
||||
<tr data-bind="visible: dateTimeStampInUTC">
|
||||
<td data-i18n="MESSAGE/LABEL_DATE"></td>
|
||||
|
@ -183,13 +183,13 @@
|
|||
<div data-bind="hidden: showFullInfo">
|
||||
<time class="date" data-moment-format="FULL" data-bind="visible: 0 < message().dateTimeStampInUTC(), moment: message().dateTimeStampInUTC()"></time>
|
||||
<div class="informationShortWrp">
|
||||
<div class="informationShort" data-bind="visible: message().toToLine()">
|
||||
<div class="informationShort" data-bind="visible: message().to.length">
|
||||
<span data-i18n="GLOBAL/TO"></span>:
|
||||
<span data-bind="text: message().toToLine()"></span>
|
||||
<span data-bind="text: message().to"></span>
|
||||
</div>
|
||||
<div class="informationShort" data-bind="visible: message().ccToLine()">
|
||||
<div class="informationShort" data-bind="visible: message().cc.length">
|
||||
<span data-i18n="GLOBAL/CC"></span>:
|
||||
<span data-bind="text: message().ccToLine()"></span>
|
||||
<span data-bind="text: message().cc"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="informationShort" data-bind="visible: message().spamResult()">
|
||||
|
@ -201,7 +201,7 @@
|
|||
<!-- ko if: tagsAllowed -->
|
||||
<div class="messageTags">
|
||||
<span data-i18n="MESSAGE/TAGS"></span>:
|
||||
<span class="messageAssignedTags" data-bind="html: message().tagsToHTML()"></span>
|
||||
<span class="messageAssignedTags" data-bind="html: tagsToHTML"></span>
|
||||
<div class="btn-group" data-bind="registerBootstrapDropdown: true" style="display: inline-block">
|
||||
<a class="btn btn-thin btn-transparent dropdown-toggle fontastic" id="tags-dropdown-id" href="#" tabindex="-1">🏷</a>
|
||||
<menu class="dropdown-menu right-edge" role="menu" aria-labelledby="tags-dropdown-id">
|
||||
|
@ -227,12 +227,12 @@
|
|||
|
||||
<div data-bind="hidden: messageLoadingThrottle">
|
||||
<div class="bodySubHeader">
|
||||
<div class="readReceipt" data-bind="visible: !isDraftOrSentFolder() && message().readReceipt() && !message().isReadReceipt(), click: readReceipt"
|
||||
<div class="readReceipt" data-bind="visible: askReadReceipt, click: readReceipt"
|
||||
data-icon="✉" data-i18n="MESSAGE/BUTTON_NOTIFY_READ_RECEIPT"></div>
|
||||
<details class="attachmentsPlace" data-bind="visible: message().hasAttachments(), css: {'selection-mode' : showAttachmentControls}">
|
||||
<details class="attachmentsPlace" data-bind="visible: hasAttachments, css: {'selection-mode' : showAttachmentControls}">
|
||||
<summary data-i18n="MESSAGE/PRINT_LABEL_ATTACHMENTS"></summary>
|
||||
<!-- ko ifnot: simpleAttachmentsList -->
|
||||
<ul class="attachmentList" data-bind="foreach: message().listAttachments()">
|
||||
<ul class="attachmentList" data-bind="foreach: listAttachments">
|
||||
<li class="attachmentItem" draggable="true"
|
||||
data-bind="event: { 'dragstart': eventDragStart }, attr: { 'title': fileName }, css: {'checked': checked}">
|
||||
<div class="attachmentIconParent" data-bind="css: { 'hasPreview': hasPreview(), 'hasPreplay': hasPreplay(), 'isImage': isImage() }">
|
||||
|
@ -259,7 +259,7 @@
|
|||
</ul>
|
||||
<!-- /ko -->
|
||||
<!-- ko if: simpleAttachmentsList -->
|
||||
<ul class="attachmentListSimple" data-bind="foreach: message().listAttachments()">
|
||||
<ul class="attachmentListSimple" data-bind="foreach: listAttachments">
|
||||
<li class="attachmentItem" data-bind="attr: { 'title': fileName }, css: {'checked': checked}">
|
||||
<span class="attachmentName" data-bind="text: fileName"></span>
|
||||
<i class="checkboxAttachment fontastic"
|
||||
|
@ -271,7 +271,7 @@
|
|||
</details>
|
||||
|
||||
<div class="attachmentsControls"
|
||||
data-bind="visible: showAttachmentControls() && message().hasAttachments()">
|
||||
data-bind="visible: showAttachmentControls() && hasAttachments()">
|
||||
|
||||
<span data-bind="visible: downloadAsZipAllowed">
|
||||
<i class="fontastic iconcolor-red" data-bind="visible: downloadAsZipError">✖</i>
|
||||
|
|
Loading…
Reference in a new issue