mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-08-29 20:19:22 +03:00
Reduce JavaScript footprint
This commit is contained in:
parent
689126c57d
commit
b12852bd08
42 changed files with 240 additions and 426 deletions
|
|
@ -27,12 +27,10 @@ export class AbstractCollectionModel extends Array
|
|||
forEachObjectEntry(json, (key, value) => '@' !== key[0] && (result[key] = value));
|
||||
json = json['@Collection'];
|
||||
}
|
||||
if (isArray(json)) {
|
||||
json.forEach(item => {
|
||||
item && itemCallback && (item = itemCallback(item, result));
|
||||
item && result.push(item);
|
||||
});
|
||||
}
|
||||
isArray(json) && json.forEach(item => {
|
||||
item && itemCallback && (item = itemCallback(item, result));
|
||||
item && result.push(item);
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,12 +38,12 @@ export class ComposeAttachmentModel extends AbstractModel {
|
|||
this.addComputables({
|
||||
progressText: () => {
|
||||
const p = this.progress();
|
||||
return 0 === p ? '' : '' + (98 < p ? 100 : p) + '%';
|
||||
return 1 > p ? '' : (100 < p ? 100 : p) + '%';
|
||||
},
|
||||
|
||||
progressStyle: () => {
|
||||
const p = this.progress();
|
||||
return 0 === p ? '' : 'width:' + (98 < p ? 100 : p) + '%';
|
||||
return 1 > p ? '' : 'width:' + (100 < p ? 100 : p) + '%';
|
||||
},
|
||||
|
||||
title: () => this.error() || this.fileName(),
|
||||
|
|
@ -54,14 +54,9 @@ export class ComposeAttachmentModel extends AbstractModel {
|
|||
},
|
||||
|
||||
mimeType: () => FileInfo.getContentType(this.fileName()),
|
||||
fileExt: () => FileInfo.getExtension(this.fileName())
|
||||
fileExt: () => FileInfo.getExtension(this.fileName()),
|
||||
|
||||
iconClass: () => FileInfo.getIconClass(this.fileExt(), this.mimeType())
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string}
|
||||
*/
|
||||
iconClass() {
|
||||
return FileInfo.getIconClass(this.fileExt(), this.mimeType());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,8 +114,6 @@ export class ContactModel extends AbstractModel {
|
|||
this.adr = ko.observableArray();
|
||||
|
||||
this.addComputables({
|
||||
hasValidName: () => !!(this.givenName() || this.surName()),
|
||||
|
||||
fullName: () => [this.namePrefix(), this.givenName(), this.middleName(), this.surName()].join(' ').trim(),
|
||||
|
||||
display: () => {
|
||||
|
|
|
|||
|
|
@ -27,18 +27,14 @@ function addressparser(str) {
|
|||
|
||||
tokens.forEach(token => {
|
||||
if (token.type === 'operator' && (token.value === ',' || token.value === ';')) {
|
||||
if (address.length) {
|
||||
addresses.push(address);
|
||||
}
|
||||
address.length && addresses.push(address);
|
||||
address = [];
|
||||
} else {
|
||||
address.push(token);
|
||||
}
|
||||
});
|
||||
|
||||
if (address.length) {
|
||||
addresses.push(address);
|
||||
}
|
||||
address.length && addresses.push(address);
|
||||
|
||||
addresses.forEach(address => {
|
||||
address = _handleAddress(address);
|
||||
|
|
@ -205,9 +201,7 @@ class Tokenizer
|
|||
|
||||
this.list.forEach(node => {
|
||||
node.value = (node.value || '').toString().trim();
|
||||
if (node.value) {
|
||||
list.push(node);
|
||||
}
|
||||
node.value && list.push(node);
|
||||
});
|
||||
|
||||
return list;
|
||||
|
|
@ -361,37 +355,26 @@ export class EmailModel extends AbstractModel {
|
|||
}
|
||||
|
||||
static splitEmailLine(line) {
|
||||
const parsedResult = addressparser(line);
|
||||
if (parsedResult.length) {
|
||||
const result = [];
|
||||
let exists = false;
|
||||
parsedResult.forEach((item) => {
|
||||
const address = item.address
|
||||
? new EmailModel(item.address.replace(/^[<]+(.*)[>]+$/g, '$1'), item.name || '')
|
||||
: null;
|
||||
const result = [];
|
||||
let exists = false;
|
||||
addressparser(line).forEach(item => {
|
||||
const address = item.address
|
||||
? new EmailModel(item.address.replace(/^[<]+(.*)[>]+$/g, '$1'), item.name || '')
|
||||
: null;
|
||||
|
||||
if (address?.email) {
|
||||
exists = true;
|
||||
}
|
||||
if (address?.email) {
|
||||
exists = true;
|
||||
}
|
||||
|
||||
result.push(address ? address.toLine() : item.name);
|
||||
});
|
||||
|
||||
return exists ? result : null;
|
||||
}
|
||||
|
||||
return null;
|
||||
result.push(address ? address.toLine() : item.name);
|
||||
});
|
||||
return exists ? result : null;
|
||||
}
|
||||
|
||||
static parseEmailLine(line) {
|
||||
const parsedResult = addressparser(line);
|
||||
if (parsedResult.length) {
|
||||
return parsedResult.map(item =>
|
||||
item.address ? new EmailModel(item.address.replace(/^[<]+(.*)[>]+$/g, '$1'), item.name || '') : null
|
||||
).filter(v => v);
|
||||
}
|
||||
|
||||
return [];
|
||||
return addressparser(line).map(item =>
|
||||
item.address ? new EmailModel(item.address.replace(/^[<]+(.*)[>]+$/g, '$1'), item.name || '') : null
|
||||
).filter(v => v);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -400,19 +383,15 @@ export class EmailModel extends AbstractModel {
|
|||
*/
|
||||
parse(emailAddress) {
|
||||
emailAddress = emailAddress.trim();
|
||||
if (!emailAddress) {
|
||||
return false;
|
||||
if (emailAddress) {
|
||||
const result = addressparser(emailAddress);
|
||||
if (result.length) {
|
||||
this.name = result[0].name || '';
|
||||
this.email = result[0].address || '';
|
||||
this.clearDuplicateName();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const result = addressparser(emailAddress);
|
||||
if (result.length) {
|
||||
this.name = result[0].name || '';
|
||||
this.email = result[0].address || '';
|
||||
this.clearDuplicateName();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,17 +21,4 @@ export class EmailCollectionModel extends AbstractCollectionModel
|
|||
toString(friendlyView, wrapWithLink) {
|
||||
return this.map(email => email.toLine(friendlyView, wrapWithLink)).join(', ');
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string}
|
||||
*/
|
||||
toStringClear() {
|
||||
const result = [];
|
||||
this.forEach(email => {
|
||||
if (email?.email && email?.name) {
|
||||
result.push(email.email);
|
||||
}
|
||||
});
|
||||
return result.join(', ');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import { MessagelistUserStore } from 'Stores/User/Messagelist';
|
|||
import { SettingsUserStore } from 'Stores/User/Settings';
|
||||
|
||||
import { sortFolders } from 'Common/Folders';
|
||||
import { i18n, trigger as translatorTrigger } from 'Common/Translator';
|
||||
import { i18n, translateTrigger } from 'Common/Translator';
|
||||
|
||||
import { AbstractModel } from 'Knoin/AbstractModel';
|
||||
|
||||
|
|
@ -76,17 +76,9 @@ export const
|
|||
*/
|
||||
setExpandedFolder = (sFullName, bExpanded) => {
|
||||
let aExpandedList = Local.get(ClientSideKeyNameExpandedFolders);
|
||||
if (!isArray(aExpandedList)) {
|
||||
aExpandedList = [];
|
||||
}
|
||||
|
||||
if (bExpanded) {
|
||||
aExpandedList.includes(sFullName) || aExpandedList.push(sFullName);
|
||||
} else {
|
||||
aExpandedList = aExpandedList.filter(value => value !== sFullName);
|
||||
}
|
||||
|
||||
Local.set(ClientSideKeyNameExpandedFolders, aExpandedList);
|
||||
aExpandedList = new Set(isArray(aExpandedList) ? aExpandedList : []);
|
||||
bExpanded ? aExpandedList.add(sFullName) : aExpandedList.delete(sFullName);
|
||||
Local.set(ClientSideKeyNameExpandedFolders, [...aExpandedList]);
|
||||
},
|
||||
|
||||
foldersFilter = ko.observable(''),
|
||||
|
|
@ -99,8 +91,7 @@ export const
|
|||
Remote.abort('Folders')
|
||||
.post('Folders', FolderUserStore.foldersLoading)
|
||||
.then(data => {
|
||||
data = FolderCollectionModel.reviveFromJson(data.Result);
|
||||
data?.storeIt();
|
||||
FolderCollectionModel.reviveFromJson(data.Result)?.storeIt();
|
||||
fCallback?.(true);
|
||||
// Repeat every 15 minutes?
|
||||
// this.foldersTimeout = setTimeout(loadFolders, 900000);
|
||||
|
|
@ -281,25 +272,15 @@ export class FolderModel extends AbstractModel {
|
|||
|
||||
this.totalEmails = koComputable({
|
||||
read: this.totalEmailsValue,
|
||||
write: (iValue) => {
|
||||
if (isPosNumeric(iValue)) {
|
||||
this.totalEmailsValue(iValue);
|
||||
} else {
|
||||
this.totalEmailsValue.valueHasMutated();
|
||||
}
|
||||
}
|
||||
write: iValue =>
|
||||
isPosNumeric(iValue) ? this.totalEmailsValue(iValue) : this.totalEmailsValue.valueHasMutated()
|
||||
})
|
||||
.extend({ notify: 'always' });
|
||||
|
||||
this.unreadEmails = koComputable({
|
||||
read: this.unreadEmailsValue,
|
||||
write: (value) => {
|
||||
if (isPosNumeric(value)) {
|
||||
this.unreadEmailsValue(value);
|
||||
} else {
|
||||
this.unreadEmailsValue.valueHasMutated();
|
||||
}
|
||||
}
|
||||
write: value =>
|
||||
isPosNumeric(value) ? this.unreadEmailsValue(value) : this.unreadEmailsValue.valueHasMutated()
|
||||
})
|
||||
.extend({ notify: 'always' });
|
||||
/*
|
||||
|
|
@ -397,13 +378,14 @@ export class FolderModel extends AbstractModel {
|
|||
const
|
||||
unread = folder.unreadEmails(),
|
||||
type = folder.type();
|
||||
// TODO: make isSystemFolder() optional in Settings
|
||||
return ((!folder.isSystemFolder() || type == FolderType.Inbox) && unread) ? unread : null;
|
||||
},
|
||||
|
||||
localName: () => {
|
||||
let name = folder.name();
|
||||
if (folder.isSystemFolder()) {
|
||||
translatorTrigger();
|
||||
translateTrigger();
|
||||
name = getSystemFolderName(folder.type(), name);
|
||||
}
|
||||
return name;
|
||||
|
|
@ -411,7 +393,7 @@ export class FolderModel extends AbstractModel {
|
|||
|
||||
manageFolderSystemName: () => {
|
||||
if (folder.isSystemFolder()) {
|
||||
translatorTrigger();
|
||||
translateTrigger();
|
||||
let suffix = getSystemFolderName(folder.type(), getKolabFolderName(folder.kolabType()));
|
||||
if (folder.name() !== suffix && 'inbox' !== suffix.toLowerCase()) {
|
||||
return '(' + suffix + ')';
|
||||
|
|
@ -420,24 +402,22 @@ export class FolderModel extends AbstractModel {
|
|||
return '';
|
||||
},
|
||||
|
||||
hasUnreadMessages: () => 0 < folder.unreadEmails() && folder.printableUnreadCount(),
|
||||
|
||||
hasSubscribedUnreadMessagesSubfolders: () =>
|
||||
!!folder.subFolders().find(
|
||||
folder => folder.hasUnreadMessages() | folder.hasSubscribedUnreadMessagesSubfolders()
|
||||
folder => folder.printableUnreadCount() | folder.hasSubscribedUnreadMessagesSubfolders()
|
||||
)
|
||||
|
||||
/*
|
||||
!!folder.subFolders().filter(
|
||||
folder => folder.printableUnreadCount() | folder.hasSubscribedUnreadMessagesSubfolders()
|
||||
).length
|
||||
*/
|
||||
// ,href: () => folder.canBeSelected() && mailBox(folder.fullNameHash)
|
||||
});
|
||||
|
||||
folder.addSubscribables({
|
||||
editing: value => value && folder.nameForEdit(folder.name()),
|
||||
|
||||
unreadEmails: unread => {
|
||||
if (FolderType.Inbox === folder.type()) {
|
||||
fireEvent('mailbox.inbox-unread-count', unread);
|
||||
}
|
||||
}
|
||||
unreadEmails: unread => FolderType.Inbox === folder.type() && fireEvent('mailbox.inbox-unread-count', unread)
|
||||
});
|
||||
}
|
||||
return folder;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
import { koComputable } from 'External/ko';
|
||||
|
||||
import { AbstractModel } from 'Knoin/AbstractModel';
|
||||
|
||||
export class IdentityModel extends AbstractModel {
|
||||
|
|
@ -23,8 +21,6 @@ export class IdentityModel extends AbstractModel {
|
|||
|
||||
askDelete: false
|
||||
});
|
||||
|
||||
this.canBeDeleted = koComputable(() => !!this.id());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { i18n } from 'Common/Translator';
|
|||
|
||||
import { doc, SettingsGet } from 'Common/Globals';
|
||||
import { encodeHtml, plainToHtml, cleanHtml } from 'Common/Html';
|
||||
import { isArray, arrayLength, forEachObjectEntry } from 'Common/Utils';
|
||||
import { arrayLength, forEachObjectEntry } from 'Common/Utils';
|
||||
import { serverRequestRaw, proxy } from 'Common/Links';
|
||||
|
||||
import { FolderUserStore, isAllowedKeyword } from 'Stores/User/Folder';
|
||||
|
|
@ -32,15 +32,12 @@ const
|
|||
|
||||
toggleTag = (message, keyword) => {
|
||||
const lower = keyword.toLowerCase(),
|
||||
isSet = message.flags().includes(lower);
|
||||
flags = message.flags,
|
||||
isSet = flags.includes(lower);
|
||||
Remote.request('MessageSetKeyword', iError => {
|
||||
if (!iError) {
|
||||
if (isSet) {
|
||||
message.flags.remove(lower);
|
||||
} else {
|
||||
message.flags.push(lower);
|
||||
}
|
||||
// MessageFlagsCache.setFor(message.folder, message.uid, message.flags());
|
||||
isSet ? flags.remove(lower) : flags.push(lower);
|
||||
// MessageFlagsCache.setFor(message.folder, message.uid, flags());
|
||||
}
|
||||
}, {
|
||||
Folder: message.folder,
|
||||
|
|
@ -56,11 +53,9 @@ const
|
|||
* @param {Map} localEmails
|
||||
*/
|
||||
replyHelper = (emails, unic, localEmails) =>
|
||||
emails.forEach(email => {
|
||||
if (!unic[email.email] && !localEmails.has(email.email)) {
|
||||
localEmails.set(email.email, email);
|
||||
}
|
||||
});
|
||||
emails.forEach(email =>
|
||||
unic[email.email] || localEmails.has(email.email) || localEmails.set(email.email, email)
|
||||
);
|
||||
|
||||
doc.body.append(hcont);
|
||||
|
||||
|
|
@ -222,16 +217,6 @@ export class MessageModel extends AbstractModel {
|
|||
return spam ? i18n(this.isSpam() ? 'GLOBAL/SPAM' : 'GLOBAL/NOT_SPAM') + ': ' + spam : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array} properties
|
||||
* @returns {Array}
|
||||
*/
|
||||
getEmails(properties) {
|
||||
return properties.reduce((carry, property) => carry.concat(this[property]), []).map(
|
||||
oItem => oItem ? oItem.email : ''
|
||||
).validUnique();
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string}
|
||||
*/
|
||||
|
|
@ -240,9 +225,11 @@ export class MessageModel extends AbstractModel {
|
|||
}
|
||||
|
||||
computeSenderEmail() {
|
||||
const list = [FolderUserStore.sentFolder(), FolderUserStore.draftsFolder()].includes(this.folder) ? 'to' : 'from';
|
||||
this.senderEmailsString(this[list].toString(true));
|
||||
this.senderClearEmailsString(this[list].toStringClear());
|
||||
const list = this[
|
||||
[FolderUserStore.sentFolder(), FolderUserStore.draftsFolder()].includes(this.folder) ? 'to' : 'from'
|
||||
];
|
||||
this.senderEmailsString(list.toString(true));
|
||||
this.senderClearEmailsString(list.map(email => email?.email).filter(email => email).join(', '));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -349,21 +336,6 @@ export class MessageModel extends AbstractModel {
|
|||
return classes.join(' ');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* https://datatracker.ietf.org/doc/html/rfc5788
|
||||
*/
|
||||
keywords() {
|
||||
return this.flags().filter(value => '\\' !== value[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string}
|
||||
*/
|
||||
fromAsSingleEmail() {
|
||||
return (isArray(this.from) && this.from[0]?.email) || '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string}
|
||||
*/
|
||||
|
|
@ -491,7 +463,7 @@ export class MessageModel extends AbstractModel {
|
|||
* @param {boolean=} print = false
|
||||
*/
|
||||
popupMessage() {
|
||||
this.viewPopupMessage(false);
|
||||
this.viewPopupMessage();
|
||||
}
|
||||
|
||||
printMessage() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue