mirror of
https://github.com/the-djmaze/snappymail.git
synced 2025-09-28 16:05:01 +08:00
Attachments array to new AttachmentCollectionModel
This commit is contained in:
parent
344edaec2a
commit
e99a69a9aa
5 changed files with 70 additions and 105 deletions
49
dev/Model/AttachmentCollection.js
Normal file
49
dev/Model/AttachmentCollection.js
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
import { AttachmentModel } from 'Model/Attachment';
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
class AttachmentCollectionModel extends Array
|
||||||
|
{
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {?Array} json
|
||||||
|
* @returns {AttachmentCollectionModel}
|
||||||
|
*/
|
||||||
|
static reviveFromJson(items, foundedCIDs) {
|
||||||
|
let result = new AttachmentCollectionModel;
|
||||||
|
if (items && 'Collection/AttachmentCollection' === items['@Object']) {
|
||||||
|
items = items['@Collection'];
|
||||||
|
}
|
||||||
|
Array.isArray(items) && items.forEach(attachment => {
|
||||||
|
attachment = AttachmentModel.newInstanceFromJson(attachment);
|
||||||
|
if (attachment) {
|
||||||
|
if (attachment.cidWithOutTags && foundedCIDs.includes(attachment.cidWithOutTags)) {
|
||||||
|
attachment.isLinked = true;
|
||||||
|
}
|
||||||
|
result.push(attachment);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
hasVisible() {
|
||||||
|
return !!this.find(item => !item.isLinked);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} cid
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
findByCid(cid) {
|
||||||
|
cid = cid.replace(/^<+|>+$/, '');
|
||||||
|
return this.find(item => cid === item.cidWithOutTags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { AttachmentCollectionModel, AttachmentCollectionModel as default };
|
|
@ -10,16 +10,14 @@ class EmailCollectionModel extends Array
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {?Array} json
|
* @param {?Array} json
|
||||||
* @returns {Array.<EmailModel>}
|
* @returns {EmailCollectionModel}
|
||||||
*/
|
*/
|
||||||
static reviveFromJson(items) {
|
static reviveFromJson(items) {
|
||||||
let result = new EmailCollectionModel;
|
let result = new EmailCollectionModel;
|
||||||
if (Array.isArray(items)) {
|
Array.isArray(items) && items.forEach(email => {
|
||||||
items.forEach(email => {
|
email = EmailModel.newInstanceFromJson(email);
|
||||||
email = EmailModel.newInstanceFromJson(email);
|
email && result.push(email);
|
||||||
email && result.push(email);
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,8 @@ import { messageViewLink, messageDownloadLink } from 'Common/Links';
|
||||||
import FolderStore from 'Stores/User/Folder';
|
import FolderStore from 'Stores/User/Folder';
|
||||||
import PgpStore from 'Stores/User/Pgp';
|
import PgpStore from 'Stores/User/Pgp';
|
||||||
|
|
||||||
import { AttachmentModel, staticCombinedIconClass } from 'Model/Attachment';
|
import { staticCombinedIconClass } from 'Model/Attachment';
|
||||||
|
import { AttachmentCollectionModel } from 'Model/AttachmentCollection';
|
||||||
import { EmailCollectionModel } from 'Model/EmailCollection';
|
import { EmailCollectionModel } from 'Model/EmailCollection';
|
||||||
import { AbstractModel } from 'Knoin/AbstractModel';
|
import { AbstractModel } from 'Knoin/AbstractModel';
|
||||||
|
|
||||||
|
@ -73,7 +74,7 @@ class MessageModel extends AbstractModel {
|
||||||
|
|
||||||
this.isHtml = ko.observable(false);
|
this.isHtml = ko.observable(false);
|
||||||
this.hasImages = ko.observable(false);
|
this.hasImages = ko.observable(false);
|
||||||
this.attachments = ko.observableArray([]);
|
this.attachments = new AttachmentCollectionModel;
|
||||||
|
|
||||||
this.isPgpSigned = ko.observable(false);
|
this.isPgpSigned = ko.observable(false);
|
||||||
this.isPgpEncrypted = ko.observable(false);
|
this.isPgpEncrypted = ko.observable(false);
|
||||||
|
@ -158,7 +159,7 @@ class MessageModel extends AbstractModel {
|
||||||
|
|
||||||
this.isHtml(false);
|
this.isHtml(false);
|
||||||
this.hasImages(false);
|
this.hasImages(false);
|
||||||
this.attachments([]);
|
this.attachments = new AttachmentCollectionModel;
|
||||||
|
|
||||||
this.isPgpSigned(false);
|
this.isPgpSigned(false);
|
||||||
this.isPgpEncrypted(false);
|
this.isPgpEncrypted(false);
|
||||||
|
@ -299,7 +300,7 @@ class MessageModel extends AbstractModel {
|
||||||
this.attachmentsSpecData(isArray(json.AttachmentsSpecData) ? json.AttachmentsSpecData : []);
|
this.attachmentsSpecData(isArray(json.AttachmentsSpecData) ? json.AttachmentsSpecData : []);
|
||||||
|
|
||||||
this.foundedCIDs = isArray(json.FoundedCIDs) ? json.FoundedCIDs : [];
|
this.foundedCIDs = isArray(json.FoundedCIDs) ? json.FoundedCIDs : [];
|
||||||
this.attachments(this.initAttachmentsFromJson(json.Attachments));
|
this.attachments = AttachmentCollectionModel.reviveFromJson(json.Attachments, this.foundedCIDs);
|
||||||
|
|
||||||
this.readReceipt(json.ReadReceipt || '');
|
this.readReceipt(json.ReadReceipt || '');
|
||||||
|
|
||||||
|
@ -311,35 +312,6 @@ class MessageModel extends AbstractModel {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {(AjaxJsonAttachment|null)} oJsonAttachments
|
|
||||||
* @returns {Array}
|
|
||||||
*/
|
|
||||||
initAttachmentsFromJson(json) {
|
|
||||||
let index = 0,
|
|
||||||
len = 0,
|
|
||||||
attachment = null;
|
|
||||||
const result = [];
|
|
||||||
|
|
||||||
if (json && 'Collection/AttachmentCollection' === json['@Object'] && Array.isNotEmpty(json['@Collection'])) {
|
|
||||||
for (index = 0, len = json['@Collection'].length; index < len; index++) {
|
|
||||||
attachment = AttachmentModel.newInstanceFromJson(json['@Collection'][index]);
|
|
||||||
if (attachment) {
|
|
||||||
if (
|
|
||||||
attachment.cidWithOutTags &&
|
|
||||||
this.foundedCIDs.includes(attachment.cidWithOutTags)
|
|
||||||
) {
|
|
||||||
attachment.isLinked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.push(attachment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
|
@ -457,44 +429,6 @@ class MessageModel extends AbstractModel {
|
||||||
return classes.join(' ');
|
return classes.join(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
hasVisibleAttachments() {
|
|
||||||
return !!this.attachments().find(item => !item.isLinked);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} cid
|
|
||||||
* @returns {*}
|
|
||||||
*/
|
|
||||||
findAttachmentByCid(cid) {
|
|
||||||
let result = null;
|
|
||||||
const attachments = this.attachments();
|
|
||||||
|
|
||||||
if (Array.isNotEmpty(attachments)) {
|
|
||||||
cid = cid.replace(/^<+/, '').replace(/>+$/, '');
|
|
||||||
result = attachments.find(item => cid === item.cidWithOutTags);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result || null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} contentLocation
|
|
||||||
* @returns {*}
|
|
||||||
*/
|
|
||||||
findAttachmentByContentLocation(contentLocation) {
|
|
||||||
let result = null;
|
|
||||||
const attachments = this.attachments();
|
|
||||||
|
|
||||||
if (Array.isNotEmpty(attachments)) {
|
|
||||||
result = attachments.find(item => contentLocation === item.contentLocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result || null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
|
@ -585,14 +519,6 @@ class MessageModel extends AbstractModel {
|
||||||
return [toResult, ccResult];
|
return [toResult, ccResult];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
attachmentsToStringLine() {
|
|
||||||
const attachLines = this.attachments().map(item => item.fileName + ' (' + item.friendlySize + ')');
|
|
||||||
return attachLines && attachLines.length ? attachLines.join(', ') : '';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {boolean=} print = false
|
* @param {boolean=} print = false
|
||||||
*/
|
*/
|
||||||
|
@ -732,18 +658,19 @@ class MessageModel extends AbstractModel {
|
||||||
if (this.body && !this.body.rlInitInternalImages) {
|
if (this.body && !this.body.rlInitInternalImages) {
|
||||||
this.body.rlInitInternalImages = true;
|
this.body.rlInitInternalImages = true;
|
||||||
|
|
||||||
const body = this.body;
|
const body = this.body,
|
||||||
|
findAttachmentByCid = cid => this.attachments.findByCid(cid);
|
||||||
|
|
||||||
body.querySelectorAll('[data-x-src-cid]').forEach(node => {
|
body.querySelectorAll('[data-x-src-cid]').forEach(node => {
|
||||||
const attachment = this.findAttachmentByCid(node.dataset.xSrcCid);
|
const attachment = findAttachmentByCid(node.dataset.xSrcCid);
|
||||||
if (attachment && attachment.download) {
|
if (attachment && attachment.download) {
|
||||||
node.src = attachment.linkPreview();
|
node.src = attachment.linkPreview();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
body.querySelectorAll('[data-x-src-location]').forEach(node => {
|
body.querySelectorAll('[data-x-src-location]').forEach(node => {
|
||||||
const attachment = this.findAttachmentByContentLocation(node.dataset.xSrcLocation)
|
const attachment = this.attachments.find(item => node.dataset.xSrcLocation === item.contentLocation)
|
||||||
|| this.findAttachmentByCid(node.dataset.xSrcLocation);
|
|| findAttachmentByCid(node.dataset.xSrcLocation);
|
||||||
if (attachment && attachment.download) {
|
if (attachment && attachment.download) {
|
||||||
if (node.matches('img')) {
|
if (node.matches('img')) {
|
||||||
node.loading = 'lazy';
|
node.loading = 'lazy';
|
||||||
|
@ -754,7 +681,7 @@ class MessageModel extends AbstractModel {
|
||||||
|
|
||||||
body.querySelectorAll('[style-cid]').forEach(node => {
|
body.querySelectorAll('[style-cid]').forEach(node => {
|
||||||
const name = node.dataset.xStyleCidName,
|
const name = node.dataset.xStyleCidName,
|
||||||
attachment = this.findAttachmentByCid(node.dataset.xStyleCid);
|
attachment = findAttachmentByCid(node.dataset.xStyleCid);
|
||||||
if (attachment && attachment.linkPreview && name) {
|
if (attachment && attachment.linkPreview && name) {
|
||||||
node.setAttribute('style', ((node.getAttribute('style')||'')
|
node.setAttribute('style', ((node.getAttribute('style')||'')
|
||||||
+ ';' + name + ": url('" + attachment.linkPreview() + "')")
|
+ ';' + name + ": url('" + attachment.linkPreview() + "')")
|
||||||
|
|
|
@ -1162,7 +1162,7 @@ class ComposePopupView extends AbstractViewNext {
|
||||||
|
|
||||||
cancelAttachmentHelper(id, oJua) {
|
cancelAttachmentHelper(id, oJua) {
|
||||||
return () => {
|
return () => {
|
||||||
const attachment = this.attachments().find(item => item && item.id === id);
|
const attachment = this.getAttachmentById(id);
|
||||||
if (attachment) {
|
if (attachment) {
|
||||||
this.attachments.remove(attachment);
|
this.attachments.remove(attachment);
|
||||||
delegateRunOnDestroy(attachment);
|
delegateRunOnDestroy(attachment);
|
||||||
|
@ -1367,8 +1367,7 @@ class ComposePopupView extends AbstractViewNext {
|
||||||
if (ComposeType.ForwardAsAttachment === type) {
|
if (ComposeType.ForwardAsAttachment === type) {
|
||||||
this.addMessageAsAttachment(message);
|
this.addMessageAsAttachment(message);
|
||||||
} else {
|
} else {
|
||||||
const attachments = message.attachments();
|
message.attachments.forEach(item => {
|
||||||
(Array.isNotEmpty(attachments) ? attachments : []).forEach(item => {
|
|
||||||
let add = false;
|
let add = false;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ComposeType.Reply:
|
case ComposeType.Reply:
|
||||||
|
@ -1409,14 +1408,6 @@ class ComposePopupView extends AbstractViewNext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
removeLinkedAttachments() {
|
|
||||||
const arrachment = this.attachments().find(item => item && item.isLinked);
|
|
||||||
if (arrachment) {
|
|
||||||
this.attachments.remove(arrachment);
|
|
||||||
delegateRunOnDestroy(arrachment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setMessageAttachmentFailedDownloadText() {
|
setMessageAttachmentFailedDownloadText() {
|
||||||
this.attachments().forEach(attachment => {
|
this.attachments().forEach(attachment => {
|
||||||
if (attachment && attachment.fromMessage) {
|
if (attachment && attachment.fromMessage) {
|
||||||
|
|
|
@ -341,9 +341,9 @@
|
||||||
|
|
||||||
<span class="i18n text" data-i18n="MESSAGE/BUTTON_NOTIFY_READ_RECEIPT"></span>
|
<span class="i18n text" data-i18n="MESSAGE/BUTTON_NOTIFY_READ_RECEIPT"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="attachmentsPlace" data-bind="visible: message() && message().hasVisibleAttachments(),
|
<div class="attachmentsPlace" data-bind="visible: message() && message().attachments.hasVisible(),
|
||||||
css: {'selection-mode' : showAttachmnetControls, 'unselectedAttachmentsError': highlightUnselectedAttachments}">
|
css: {'selection-mode' : showAttachmnetControls, 'unselectedAttachmentsError': highlightUnselectedAttachments}">
|
||||||
<ul class="attachmentList" data-bind="foreach: message() ? message().attachments() : []">
|
<ul class="attachmentList" data-bind="foreach: message() ? message().attachments : []">
|
||||||
<li class="attachmentItem clearfix" draggable="true" data-tooltip-join="top"
|
<li class="attachmentItem clearfix" draggable="true" data-tooltip-join="top"
|
||||||
data-bind="visible: !isLinked, event: { 'dragstart': eventDragStart }, attr: { 'title': fileName }, css: {'checked': checked}">
|
data-bind="visible: !isLinked, event: { 'dragstart': eventDragStart }, attr: { 'title': fileName }, css: {'checked': checked}">
|
||||||
<div class="attachmentIconParent pull-left" data-bind="css: { 'hasPreview': hasPreview(), 'hasPreplay': hasPreplay(), 'isImage': isImage() }">
|
<div class="attachmentIconParent pull-left" data-bind="css: { 'hasPreview': hasPreview(), 'hasPreplay': hasPreplay(), 'isImage': isImage() }">
|
||||||
|
@ -393,7 +393,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="attachmentsControls"
|
<div class="attachmentsControls"
|
||||||
data-bind="visible: showAttachmnetControls() && message() && message().hasVisibleAttachments()">
|
data-bind="visible: showAttachmnetControls() && message() && message().attachments.hasVisible()">
|
||||||
|
|
||||||
<span data-bind="visible: downloadAsZipAllowed">
|
<span data-bind="visible: downloadAsZipAllowed">
|
||||||
<i class="icon-remove iconcolor-red" data-bind="visible: downloadAsZipError"></i>
|
<i class="icon-remove iconcolor-red" data-bind="visible: downloadAsZipError"></i>
|
||||||
|
|
Loading…
Add table
Reference in a new issue