Merge Objects prototype extensions

This commit is contained in:
djmaze 2020-09-04 17:07:35 +02:00
parent 0647b5201f
commit f2d194947d
26 changed files with 108 additions and 127 deletions

View file

@ -86,21 +86,21 @@ Things might work in Edge 18, Firefox 50-62 and Chrome 54-68 due to one polyfill
|js/* |1.14.0 |native | |js/* |1.14.0 |native |
|----------- |--------: |--------: | |----------- |--------: |--------: |
|admin.js |2.130.942 | 939.722 | |admin.js |2.130.942 | 938.738 |
|app.js |4.184.455 |2.559.620 | |app.js |4.184.455 |2.556.224 |
|boot.js | 671.522 | 7.265 | |boot.js | 671.522 | 7.265 |
|libs.js | 647.614 | 312.269 | |libs.js | 647.614 | 312.343 |
|polyfills.js | 325.834 | 0 | |polyfills.js | 325.834 | 0 |
|TOTAL |7.960.367 |3.818.876 | |TOTAL |7.960.367 |3.814.570 |
|js/min/* |1.14.0 |native |gzip 1.14 |gzip |brotli | |js/min/* |1.14.0 |native |gzip 1.14 |gzip |brotli |
|--------------- |--------: |--------: |--------: |--------: |--------: | |--------------- |--------: |--------: |--------: |--------: |--------: |
|admin.min.js | 252.147 | 128.874 | 73.657 | 37.574 | 32.236 | |admin.min.js | 252.147 | 128.761 | 73.657 | 37.546 | 32.178 |
|app.min.js | 511.202 | 349.777 |140.462 | 91.836 | 73.775 | |app.min.js | 511.202 | 349.280 |140.462 | 91.746 | 73.635 |
|boot.min.js | 66.007 | 4.258 | 22.567 | 1.946 | 1.648 | |boot.min.js | 66.007 | 4.258 | 22.567 | 1.946 | 1.648 |
|libs.min.js | 572.545 | 295.716 |176.720 | 91.532 | 80.863 | |libs.min.js | 572.545 | 295.754 |176.720 | 91.521 | 80.871 |
|polyfills.min.js | 32.452 | 0 | 11.312 | 0 | 0 | |polyfills.min.js | 32.452 | 0 | 11.312 | 0 | 0 |
|TOTAL |1.434.353 | 778.625 |424.718 |222.888 |188.522 | |TOTAL |1.434.353 | 778.053 |424.718 |222.759 |188.332 |
655.728 bytes (201.830 gzip) is not much, but it feels faster. 655.728 bytes (201.830 gzip) is not much, but it feels faster.

View file

@ -1,6 +1,5 @@
import { import {
isPosNumeric, isPosNumeric,
isNonEmptyArray,
pInt, pInt,
pString, pString,
delegateRunOnDestroy, delegateRunOnDestroy,
@ -89,9 +88,9 @@ class AppUser extends AbstractApp {
// wakeUp // wakeUp
const interval = 3600000; // 60m const interval = 3600000; // 60m
var lastTime = (new Date()).getTime(); var lastTime = Date.now();
setInterval(() => { setInterval(() => {
const currentTime = (new Date()).getTime(); const currentTime = Date.now();
if (currentTime > (lastTime + interval + 1000)) { if (currentTime > (lastTime + interval + 1000)) {
if (rl.hash.check()) { if (rl.hash.check()) {
this.reload(); this.reload();
@ -645,10 +644,10 @@ class AppUser extends AbstractApp {
*/ */
folderInformationMultiply(boot = false) { folderInformationMultiply(boot = false) {
const folders = FolderStore.getNextFolderNames(); const folders = FolderStore.getNextFolderNames();
if (isNonEmptyArray(folders)) { if (Array.isNotEmpty(folders)) {
Remote.folderInformationMultiply((sResult, oData) => { Remote.folderInformationMultiply((sResult, oData) => {
if (StorageResultType.Success === sResult) { if (StorageResultType.Success === sResult) {
if (oData && oData.Result && oData.Result.List && isNonEmptyArray(oData.Result.List)) { if (oData && oData.Result && oData.Result.List && Array.isNotEmpty(oData.Result.List)) {
const utc = Date.now() / 1000; const utc = Date.now() / 1000;
oData.Result.List.forEach(item => { oData.Result.List.forEach(item => {
const hash = getFolderHash(item.Folder), const hash = getFolderHash(item.Folder),
@ -685,7 +684,7 @@ class AppUser extends AbstractApp {
} else if (unreadCountChange) { } else if (unreadCountChange) {
if (folder.fullNameRaw === FolderStore.currentFolderFullNameRaw()) { if (folder.fullNameRaw === FolderStore.currentFolderFullNameRaw()) {
const list = MessageStore.messageList(); const list = MessageStore.messageList();
if (isNonEmptyArray(list)) { if (Array.isNotEmpty(list)) {
this.folderInformation(folder.fullNameRaw, list); this.folderInformation(folder.fullNameRaw, list);
} }
} }

View file

@ -265,7 +265,7 @@ export function storeMessageFlagsToCache(message) {
* @param {Array} flags * @param {Array} flags
*/ */
export function storeMessageFlagsToCacheByFolderAndUid(folder, uid, flags) { export function storeMessageFlagsToCacheByFolderAndUid(folder, uid, flags) {
if (Array.isArray(flags) && flags.length) { if (Array.isNotEmpty(flags)) {
setMessageFlagsToCache(folder, uid, flags); setMessageFlagsToCache(folder, uid, flags);
} }
} }
@ -279,7 +279,7 @@ export function storeMessageFlagsToCacheBySetAction(folder, uid, setAction) {
let unread = 0; let unread = 0;
const flags = getMessageFlagsFromCache(folder, uid); const flags = getMessageFlagsFromCache(folder, uid);
if (Array.isArray(flags) && flags.length) { if (Array.isNotEmpty(flags)) {
if (flags[0]) { if (flags[0]) {
unread = 1; unread = 1;
} }

View file

@ -41,14 +41,6 @@ export function pString(value) {
return null != value ? '' + value : ''; return null != value ? '' + value : '';
} }
/**
* @param {*} values
* @returns {boolean}
*/
export function isNonEmptyArray(values) {
return isArray(values) && values.length;
}
/** /**
* @param {string} queryString * @param {string} queryString
* @returns {Object} * @returns {Object}

2
dev/External/ko.js vendored
View file

@ -485,7 +485,7 @@ ko.extenders.limitedList = (target, limitedList) => {
const currentValue = ko.unwrap(target), const currentValue = ko.unwrap(target),
list = ko.unwrap(limitedList); list = ko.unwrap(limitedList);
if (Array.isArray(list) && list.length) { if (Array.isNotEmpty(list)) {
if (list.includes(newValue)) { if (list.includes(newValue)) {
target(newValue); target(newValue);
} else if (list.includes(currentValue, list)) { } else if (list.includes(currentValue, list)) {

View file

@ -1,4 +1,3 @@
import { isNonEmptyArray } from 'Common/Utils';
import { EmailModel } from 'Model/Email'; import { EmailModel } from 'Model/Email';
/** /**
@ -9,7 +8,7 @@ import { EmailModel } from 'Model/Email';
*/ */
export function emailArrayToString(emails, friendlyView = false, wrapWithLink = false) { export function emailArrayToString(emails, friendlyView = false, wrapWithLink = false) {
const result = []; const result = [];
if (isNonEmptyArray(emails)) { if (Array.isNotEmpty(emails)) {
emails.forEach(email => result.push(email.toLine(friendlyView, wrapWithLink))); emails.forEach(email => result.push(email.toLine(friendlyView, wrapWithLink)));
} }
@ -22,7 +21,7 @@ export function emailArrayToString(emails, friendlyView = false, wrapWithLink =
*/ */
export function emailArrayToStringClear(emails) { export function emailArrayToStringClear(emails) {
const result = []; const result = [];
if (isNonEmptyArray(emails)) { if (Array.isNotEmpty(emails)) {
emails.forEach(email => { emails.forEach(email => {
if (email && email.email && email.name) { if (email && email.email && email.name) {
result.push(email.email); result.push(email.email);
@ -39,7 +38,7 @@ export function emailArrayToStringClear(emails) {
*/ */
export function emailArrayFromJson(json) { export function emailArrayFromJson(json) {
const result = []; const result = [];
if (isNonEmptyArray(json)) { if (Array.isNotEmpty(json)) {
json.forEach(email => { json.forEach(email => {
email = EmailModel.newInstanceFromJson(email); email = EmailModel.newInstanceFromJson(email);
if (email) { if (email) {

View file

@ -44,7 +44,7 @@ export class AbstractScreen {
fMatcher = null; fMatcher = null;
const routes = this.routes(); const routes = this.routes();
if (Array.isArray(routes) && routes.length) { if (Array.isNotEmpty(routes)) {
fMatcher = (this.onRoute || (()=>{})).bind(this); fMatcher = (this.onRoute || (()=>{})).bind(this);
route = new Crossroads(); route = new Crossroads();

View file

@ -12,7 +12,7 @@ let currentScreen = null,
const SCREENS = {}, const SCREENS = {},
qs = s => document.querySelector(s), qs = s => document.querySelector(s),
isNonEmptyArray = values => Array.isArray(values) && values.length, isNonEmptyArray = Array.isNotEmpty,
autofocus = dom => { autofocus = dom => {
// if (!bMobileDevice) { // if (!bMobileDevice) {
const af = dom.querySelector('[autofocus]'); const af = dom.querySelector('[autofocus]');

View file

@ -2,7 +2,7 @@ import ko from 'ko';
import { FileType } from 'Common/Enums'; import { FileType } from 'Common/Enums';
import { bMobileDevice } from 'Common/Globals'; import { bMobileDevice } from 'Common/Globals';
import { pInt, isNonEmptyArray, getFileExtension, friendlySize } from 'Common/Utils'; import { pInt, getFileExtension, friendlySize } from 'Common/Utils';
import { import {
attachmentDownload, attachmentDownload,
attachmentPreview, attachmentPreview,
@ -149,7 +149,7 @@ export const staticCombinedIconClass = (data) => {
let result = '', let result = '',
types = []; types = [];
if (isNonEmptyArray(data)) { if (Array.isNotEmpty(data)) {
result = 'icon-attachment'; result = 'icon-attachment';
types = data.map(item => item ? staticFileType(getFileExtension(item[0]), item[1]) : '') types = data.map(item => item ? staticFileType(getFileExtension(item[0]), item[1]) : '')
.filter((value, index, self) => !!value && self.indexOf(value) == index); .filter((value, index, self) => !!value && self.indexOf(value) == index);

View file

@ -1,7 +1,7 @@
import ko from 'ko'; import ko from 'ko';
import { ContactPropertyType } from 'Common/Enums'; import { ContactPropertyType } from 'Common/Enums';
import { isNonEmptyArray, pInt, pString } from 'Common/Utils'; import { pInt, pString } from 'Common/Utils';
import { emptyContactPic } from 'Common/Links'; import { emptyContactPic } from 'Common/Links';
import { AbstractModel } from 'Knoin/AbstractModel'; import { AbstractModel } from 'Knoin/AbstractModel';
@ -28,7 +28,7 @@ class ContactModel extends AbstractModel {
let name = '', let name = '',
email = ''; email = '';
if (isNonEmptyArray(this.properties)) { if (Array.isNotEmpty(this.properties)) {
this.properties.forEach(property => { this.properties.forEach(property => {
if (property) { if (property) {
if (ContactPropertyType.FirstName === property[0]) { if (ContactPropertyType.FirstName === property[0]) {
@ -56,7 +56,7 @@ class ContactModel extends AbstractModel {
this.display = pString(json.Display); this.display = pString(json.Display);
this.readOnly = !!json.ReadOnly; this.readOnly = !!json.ReadOnly;
if (isNonEmptyArray(json.Properties)) { if (Array.isNotEmpty(json.Properties)) {
json.Properties.forEach(property => { json.Properties.forEach(property => {
if (property && property.Type && null != property.Value && null != property.TypeStr) { if (property && property.Type && null != property.Value && null != property.TypeStr) {
this.properties.push([pInt(property.Type), pString(property.Value), pString(property.TypeStr)]); this.properties.push([pInt(property.Type), pString(property.Value), pString(property.TypeStr)]);

View file

@ -1,7 +1,7 @@
import ko from 'ko'; import ko from 'ko';
import { FilterRulesType, FiltersAction } from 'Common/Enums'; import { FilterRulesType, FiltersAction } from 'Common/Enums';
import { pString, isNonEmptyArray, fakeMd5, delegateRunOnDestroy } from 'Common/Utils'; import { pString, fakeMd5, delegateRunOnDestroy } from 'Common/Utils';
import { i18n } from 'Common/Translator'; import { i18n } from 'Common/Translator';
import { getFolderFromCacheList } from 'Common/Cache'; import { getFolderFromCacheList } from 'Common/Cache';
@ -225,7 +225,7 @@ class FilterModel extends AbstractModel {
this.conditions([]); this.conditions([]);
if (isNonEmptyArray(json.Conditions)) { if (Array.isNotEmpty(json.Conditions)) {
this.conditions( this.conditions(
json.Conditions.map(aData => { json.Conditions.map(aData => {
const filterCondition = new FilterConditionModel(); const filterCondition = new FilterConditionModel();

View file

@ -7,8 +7,7 @@ import {
pInt, pInt,
deModule, deModule,
encodeHtml, encodeHtml,
friendlySize, friendlySize
isNonEmptyArray
} from 'Common/Utils'; } from 'Common/Utils';
import { messageViewLink, messageDownloadLink } from 'Common/Links'; import { messageViewLink, messageDownloadLink } from 'Common/Links';
@ -257,7 +256,7 @@ class MessageModel extends AbstractModel {
this.bcc = emailArrayFromJson(json.Bcc); this.bcc = emailArrayFromJson(json.Bcc);
this.replyTo = emailArrayFromJson(json.ReplyTo); this.replyTo = emailArrayFromJson(json.ReplyTo);
this.deliveredTo = emailArrayFromJson(json.DeliveredTo); this.deliveredTo = emailArrayFromJson(json.DeliveredTo);
this.unsubsribeLinks = isNonEmptyArray(json.UnsubsribeLinks) ? json.UnsubsribeLinks : []; this.unsubsribeLinks = Array.isNotEmpty(json.UnsubsribeLinks) ? json.UnsubsribeLinks : [];
this.subject(json.Subject); this.subject(json.Subject);
if (isArray(json.SubjectParts)) { if (isArray(json.SubjectParts)) {
@ -341,7 +340,7 @@ class MessageModel extends AbstractModel {
attachment = null; attachment = null;
const result = []; const result = [];
if (json && 'Collection/AttachmentCollection' === json['@Object'] && isNonEmptyArray(json['@Collection'])) { if (json && 'Collection/AttachmentCollection' === json['@Object'] && Array.isNotEmpty(json['@Collection'])) {
for (index = 0, len = json['@Collection'].length; index < len; index++) { for (index = 0, len = json['@Collection'].length; index < len; index++) {
attachment = AttachmentModel.newInstanceFromJson(json['@Collection'][index]); attachment = AttachmentModel.newInstanceFromJson(json['@Collection'][index]);
if (attachment) { if (attachment) {
@ -408,7 +407,7 @@ class MessageModel extends AbstractModel {
*/ */
fromDkimData() { fromDkimData() {
let result = ['none', '']; let result = ['none', ''];
if (isNonEmptyArray(this.from) && 1 === this.from.length && this.from[0] && this.from[0].dkimStatus) { if (Array.isNotEmpty(this.from) && 1 === this.from.length && this.from[0] && this.from[0].dkimStatus) {
result = [this.from[0].dkimStatus, this.from[0].dkimValue || '']; result = [this.from[0].dkimStatus, this.from[0].dkimValue || ''];
} }
@ -492,7 +491,7 @@ class MessageModel extends AbstractModel {
let result = null; let result = null;
const attachments = this.attachments(); const attachments = this.attachments();
if (isNonEmptyArray(attachments)) { if (Array.isNotEmpty(attachments)) {
cid = cid.replace(/^<+/, '').replace(/>+$/, ''); cid = cid.replace(/^<+/, '').replace(/>+$/, '');
result = attachments.find(item => cid === item.cidWithOutTags); result = attachments.find(item => cid === item.cidWithOutTags);
} }
@ -508,7 +507,7 @@ class MessageModel extends AbstractModel {
let result = null; let result = null;
const attachments = this.attachments(); const attachments = this.attachments();
if (isNonEmptyArray(attachments)) { if (Array.isNotEmpty(attachments)) {
result = attachments.find(item => contentLocation === item.contentLocation); result = attachments.find(item => contentLocation === item.contentLocation);
} }

View file

@ -1,7 +1,5 @@
import ko from 'ko'; import ko from 'ko';
import { isNonEmptyArray } from 'Common/Utils';
import { AbstractModel } from 'Knoin/AbstractModel'; import { AbstractModel } from 'Knoin/AbstractModel';
import PgpStore from 'Stores/User/Pgp'; import PgpStore from 'Stores/User/Pgp';
@ -23,7 +21,7 @@ class OpenPgpKeyModel extends AbstractModel {
this.index = index; this.index = index;
this.id = ID; this.id = ID;
this.ids = isNonEmptyArray(IDs) ? IDs : [ID]; this.ids = Array.isNotEmpty(IDs) ? IDs : [ID];
this.guid = guID; this.guid = guID;
this.user = ''; this.user = '';
this.users = userIDs; this.users = userIDs;

View file

@ -445,7 +445,7 @@ class RemoteUserAjax extends AbstractAjaxRemote {
let request = true; let request = true;
const uids = []; const uids = [];
if (Array.isArray(list) && list.length) { if (Array.isNotEmpty(list)) {
request = false; request = false;
list.forEach(messageListItem => { list.forEach(messageListItem => {
if (!getMessageFlagsFromCache(messageListItem.folderFullNameRaw, messageListItem.uid)) { if (!getMessageFlagsFromCache(messageListItem.folderFullNameRaw, messageListItem.uid)) {

View file

@ -2,7 +2,6 @@ import ko from 'ko';
import { Focused, KeyState } from 'Common/Enums'; import { Focused, KeyState } from 'Common/Enums';
import { keyScope, leftPanelDisabled } from 'Common/Globals'; import { keyScope, leftPanelDisabled } from 'Common/Globals';
import { isNonEmptyArray } from 'Common/Utils';
import { AbstractAppStore } from 'Stores/AbstractApp'; import { AbstractAppStore } from 'Stores/AbstractApp';
@ -70,7 +69,7 @@ class AppUserStore extends AbstractAppStore {
this.contactsIsAllowed(!!Settings.get('ContactsIsAllowed')); this.contactsIsAllowed(!!Settings.get('ContactsIsAllowed'));
const attachmentsActions = Settings.app('attachmentsActions'); const attachmentsActions = Settings.app('attachmentsActions');
this.attachmentsActions(isNonEmptyArray(attachmentsActions) ? attachmentsActions : []); this.attachmentsActions(Array.isNotEmpty(attachmentsActions) ? attachmentsActions : []);
this.devEmail = Settings.get('DevEmail'); this.devEmail = Settings.get('DevEmail');
this.devPassword = Settings.get('DevPassword'); this.devPassword = Settings.get('DevPassword');

View file

@ -68,7 +68,7 @@ class FolderUserStore {
trashFolder = this.trashFolder(), trashFolder = this.trashFolder(),
archiveFolder = this.archiveFolder(); archiveFolder = this.archiveFolder();
if (Array.isArray(folders) && folders.length) { if (Array.isNotEmpty(folders)) {
if (sentFolder && UNUSED_OPTION_VALUE !== sentFolder) { if (sentFolder && UNUSED_OPTION_VALUE !== sentFolder) {
list.push(sentFolder); list.push(sentFolder);
} }

View file

@ -240,7 +240,7 @@ class MessageUserStore {
initUidNextAndNewMessages(folder, uidNext, newMessages) { initUidNextAndNewMessages(folder, uidNext, newMessages) {
if (getFolderInboxName() === folder && uidNext) { if (getFolderInboxName() === folder && uidNext) {
if (Array.isArray(newMessages) && newMessages.length) { if (Array.isNotEmpty(newMessages)) {
newMessages.forEach(item => { newMessages.forEach(item => {
addNewMessageCache(folder, item.Uid); addNewMessageCache(folder, item.Uid);
}); });

View file

@ -1,7 +1,7 @@
import ko from 'ko'; import ko from 'ko';
import { i18n } from 'Common/Translator'; import { i18n } from 'Common/Translator';
import { isNonEmptyArray, pString } from 'Common/Utils'; import { pString } from 'Common/Utils';
import AccountStore from 'Stores/User/Account'; import AccountStore from 'Stores/User/Account';
@ -51,7 +51,7 @@ function domControlEncryptedClickHelper(store, dom, armoredMessage, recipients)
decryptedMessage.getText() decryptedMessage.getText()
); );
} else if (validPrivateKey) { } else if (validPrivateKey) {
const keyIds = isNonEmptyArray(signingKeyIds) ? signingKeyIds : null, const keyIds = Array.isNotEmpty(signingKeyIds) ? signingKeyIds : null,
additional = keyIds additional = keyIds
? keyIds.map(item => (item && item.toHex ? item.toHex() : null)).filter(value => !!value).join(', ') ? keyIds.map(item => (item && item.toHex ? item.toHex() : null)).filter(value => !!value).join(', ')
: ''; : '';
@ -107,7 +107,7 @@ function domControlSignedClickHelper(store, dom, armoredMessage) {
message.getText() message.getText()
); );
} else { } else {
const keyIds = isNonEmptyArray(signingKeyIds) ? signingKeyIds : null, const keyIds = Array.isNotEmpty(signingKeyIds) ? signingKeyIds : null,
additional = keyIds additional = keyIds
? keyIds.map(item => (item && item.toHex ? item.toHex() : null)).filter(value => !!value).join(', ') ? keyIds.map(item => (item && item.toHex ? item.toHex() : null)).filter(value => !!value).join(', ')
: ''; : '';
@ -183,7 +183,7 @@ class PgpUserStore {
}).flat().filter(value => !!value) }).flat().filter(value => !!value)
: []; : [];
if (!result.length && isNonEmptyArray(recipients)) { if (!result.length && Array.isNotEmpty(recipients)) {
result = recipients.map(sEmail => { result = recipients.map(sEmail => {
const keys = sEmail ? this.findAllPrivateKeysByEmailNotNative(sEmail) : null; const keys = sEmail ? this.findAllPrivateKeysByEmailNotNative(sEmail) : null;
return keys return keys

View file

@ -12,7 +12,6 @@ import {
} from 'Common/Enums'; } from 'Common/Enums';
import { import {
isNonEmptyArray,
replySubjectAdd, replySubjectAdd,
encodeHtml, encodeHtml,
inFocus, inFocus,
@ -263,7 +262,7 @@ class ComposePopupView extends AbstractViewNext {
}); });
this.attachmentsInProcess.subscribe(value => { this.attachmentsInProcess.subscribe(value => {
if (this.attachmentsInProcessError() && isNonEmptyArray(value)) { if (this.attachmentsInProcessError() && Array.isNotEmpty(value)) {
this.attachmentsInProcessError(false); this.attachmentsInProcessError(false);
} }
}); });
@ -772,7 +771,7 @@ class ComposePopupView extends AbstractViewNext {
* @param {Array} emails * @param {Array} emails
*/ */
addEmailsTo(fKoValue, emails) { addEmailsTo(fKoValue, emails) {
if (isNonEmptyArray(emails)) { if (Array.isNotEmpty(emails)) {
const value = fKoValue().trim(), const value = fKoValue().trim(),
values = emails.map(item => item ? item.toLine(false) : null) values = emails.map(item => item ? item.toLine(false) : null)
.filter((value, index, self) => !!value && self.indexOf(value) == index); .filter((value, index, self) => !!value && self.indexOf(value) == index);
@ -842,15 +841,15 @@ class ComposePopupView extends AbstractViewNext {
excludeEmail[identity.email()] = true; excludeEmail[identity.email()] = true;
} }
if (isNonEmptyArray(aToEmails)) { if (Array.isNotEmpty(aToEmails)) {
this.to(this.emailArrayToStringLineHelper(aToEmails)); this.to(this.emailArrayToStringLineHelper(aToEmails));
} }
if (isNonEmptyArray(aCcEmails)) { if (Array.isNotEmpty(aCcEmails)) {
this.cc(this.emailArrayToStringLineHelper(aCcEmails)); this.cc(this.emailArrayToStringLineHelper(aCcEmails));
} }
if (isNonEmptyArray(aBccEmails)) { if (Array.isNotEmpty(aBccEmails)) {
this.bcc(this.emailArrayToStringLineHelper(aBccEmails)); this.bcc(this.emailArrayToStringLineHelper(aBccEmails));
} }
@ -915,7 +914,7 @@ class ComposePopupView extends AbstractViewNext {
this.subject(sSubject); this.subject(sSubject);
this.prepearMessageAttachments(message, lineComposeType); this.prepearMessageAttachments(message, lineComposeType);
this.aDraftInfo = isNonEmptyArray(aDraftInfo) && 3 === aDraftInfo.length ? aDraftInfo : null; this.aDraftInfo = Array.isNotEmpty(aDraftInfo) && 3 === aDraftInfo.length ? aDraftInfo : null;
this.sInReplyTo = message.sInReplyTo; this.sInReplyTo = message.sInReplyTo;
this.sReferences = message.sReferences; this.sReferences = message.sReferences;
break; break;
@ -929,7 +928,7 @@ class ComposePopupView extends AbstractViewNext {
this.subject(sSubject); this.subject(sSubject);
this.prepearMessageAttachments(message, lineComposeType); this.prepearMessageAttachments(message, lineComposeType);
this.aDraftInfo = isNonEmptyArray(aDraftInfo) && 3 === aDraftInfo.length ? aDraftInfo : null; this.aDraftInfo = Array.isNotEmpty(aDraftInfo) && 3 === aDraftInfo.length ? aDraftInfo : null;
this.sInReplyTo = message.sInReplyTo; this.sInReplyTo = message.sInReplyTo;
this.sReferences = message.sReferences; this.sReferences = message.sReferences;
break; break;
@ -1021,7 +1020,7 @@ class ComposePopupView extends AbstractViewNext {
this.setFocusInPopup(); this.setFocusInPopup();
}); });
} else if (isNonEmptyArray(oMessageOrArray)) { } else if (Array.isNotEmpty(oMessageOrArray)) {
oMessageOrArray.forEach(item => { oMessageOrArray.forEach(item => {
this.addMessageAsAttachment(item); this.addMessageAsAttachment(item);
}); });
@ -1047,7 +1046,7 @@ class ComposePopupView extends AbstractViewNext {
} }
const downloads = this.getAttachmentsDownloadsForUpload(); const downloads = this.getAttachmentsDownloadsForUpload();
if (isNonEmptyArray(downloads)) { if (Array.isNotEmpty(downloads)) {
Remote.messageUploadAttachments(()=>this.onMessageUploadAttachments(), downloads); Remote.messageUploadAttachments(()=>this.onMessageUploadAttachments(), downloads);
} }
@ -1375,7 +1374,7 @@ class ComposePopupView extends AbstractViewNext {
this.addMessageAsAttachment(message); this.addMessageAsAttachment(message);
} else { } else {
const attachments = message.attachments(); const attachments = message.attachments();
(isNonEmptyArray(attachments) ? 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:

View file

@ -13,7 +13,6 @@ import {
import { import {
delegateRunOnDestroy, delegateRunOnDestroy,
computedPagenatorHelper, computedPagenatorHelper,
isNonEmptyArray,
fakeMd5, fakeMd5,
pInt pInt
} from 'Common/Utils'; } from 'Common/Utils';
@ -229,7 +228,7 @@ class ContactsPopupView extends AbstractViewNext {
bccEmails = null; bccEmails = null;
const aC = this.contactsCheckedOrSelected(); const aC = this.contactsCheckedOrSelected();
if (isNonEmptyArray(aC)) { if (Array.isNotEmpty(aC)) {
aE = aC.map(oItem => { aE = aC.map(oItem => {
if (oItem) { if (oItem) {
const data = oItem.getNameAndEmailHelper(), const data = oItem.getNameAndEmailHelper(),
@ -246,7 +245,7 @@ class ContactsPopupView extends AbstractViewNext {
aE = aE.filter(value => !!value); aE = aE.filter(value => !!value);
} }
if (isNonEmptyArray(aE)) { if (Array.isNotEmpty(aE)) {
this.bBackToCompose = false; this.bBackToCompose = false;
hideScreenPopup(ContactsPopupView); hideScreenPopup(ContactsPopupView);
@ -511,7 +510,7 @@ class ContactsPopupView extends AbstractViewNext {
if (contact) { if (contact) {
id = contact.idContact; id = contact.idContact;
if (isNonEmptyArray(contact.properties)) { if (Array.isNotEmpty(contact.properties)) {
contact.properties.forEach(property => { contact.properties.forEach(property => {
if (property && property[0]) { if (property && property[0]) {
if (ContactPropertyType.LastName === property[0]) { if (ContactPropertyType.LastName === property[0]) {
@ -579,7 +578,7 @@ class ContactsPopupView extends AbstractViewNext {
list = []; list = [];
if (StorageResultType.Success === result && data && data.Result && data.Result.List) { if (StorageResultType.Success === result && data && data.Result && data.Result.List) {
if (isNonEmptyArray(data.Result.List)) { if (Array.isNotEmpty(data.Result.List)) {
list = data.Result.List.map(item => { list = data.Result.List.map(item => {
const contact = new ContactModel(); const contact = new ContactModel();
return contact.parse(item) ? contact : null; return contact.parse(item) ? contact : null;

View file

@ -83,7 +83,7 @@ class PluginPopupView extends AbstractViewNext {
this.readme(oPlugin.Readme); this.readme(oPlugin.Readme);
const config = oPlugin.Config; const config = oPlugin.Config;
if (Array.isArray(config) && config.length) { if (Array.isNotEmpty(config)) {
this.configures( this.configures(
config.map(item => ({ config.map(item => ({
'value': ko.observable(item[0]), 'value': ko.observable(item[0]),

View file

@ -16,7 +16,6 @@ import {
import { $htmlCL, leftPanelDisabled, keyScopeReal, useKeyboardShortcuts, moveAction } from 'Common/Globals'; import { $htmlCL, leftPanelDisabled, keyScopeReal, useKeyboardShortcuts, moveAction } from 'Common/Globals';
import { import {
isNonEmptyArray,
inFocus, inFocus,
removeSelection, removeSelection,
removeInFocus, removeInFocus,
@ -213,7 +212,7 @@ class MessageViewMailBoxUserView extends AbstractViewNext {
this.viewFromDkimStatusTitle = ko.computed(() => { this.viewFromDkimStatusTitle = ko.computed(() => {
const status = this.viewFromDkimData(); const status = this.viewFromDkimData();
if (isNonEmptyArray(status)) { if (Array.isNotEmpty(status)) {
if (status[0] && status[1]) { if (status[0] && status[1]) {
return status[1]; return status[1];
} else if (status[0]) { } else if (status[0]) {

View file

@ -1,13 +0,0 @@
(()=>{
Element.prototype.closestWithin = function(selector, parent) {
const el = this.closest(selector);
return (el && el !== parent && parent.contains(el)) ? el : null;
};
Element.fromHTML = string => {
const template = document.createElement('template');
template.innerHTML = string.trim();
return template.content.firstChild;
};
})();

View file

@ -1,34 +0,0 @@
/**
* Every time the function is executed,
* it will delay the execution with the given amount of milliseconds.
*/
if (!Function.prototype.debounce) {
Function.prototype.debounce = function(ms) {
let func = this, timer;
return function(...args) {
timer && clearTimeout(timer);
timer = setTimeout(()=>{
func.apply(this, args)
timer = 0;
}, ms);
};
};
}
/**
* No matter how many times the event is executed,
* the function will be executed only once, after the given amount of milliseconds.
*/
if (!Function.prototype.throttle) {
Function.prototype.throttle = function(ms) {
let func = this, timer;
return function(...args) {
if (!timer) {
timer = setTimeout(()=>{
func.apply(this, args)
timer = 0;
}, ms);
}
};
};
}

View file

@ -1,5 +1,6 @@
(w=>{ (w=>{
Array.isNotEmpty = array => Array.isArray(array) && array.length;
// Import momentjs locales function // Import momentjs locales function
w.moment = { w.moment = {
@ -167,7 +168,7 @@
// Simulate momentjs fromNow function // Simulate momentjs fromNow function
Date.prototype.fromNow = function() { Date.prototype.fromNow = function() {
let format, let format,
seconds = ((new Date()).getTime() - this.getTime()) / 1000, seconds = (Date.now() - this.getTime()) / 1000,
str = locale.relativeTime[0 < seconds ? 'past' : 'future']; str = locale.relativeTime[0 < seconds ? 'past' : 'future'];
seconds = Math.abs(seconds); seconds = Math.abs(seconds);
if (60 > seconds) { if (60 > seconds) {
@ -195,4 +196,50 @@
return str.replace('%s', locale.relativeTime[format].replace('%d', seconds)); return str.replace('%s', locale.relativeTime[format].replace('%d', seconds));
} }
Element.prototype.closestWithin = function(selector, parent) {
const el = this.closest(selector);
return (el && el !== parent && parent.contains(el)) ? el : null;
};
Element.fromHTML = string => {
const template = document.createElement('template');
template.innerHTML = string.trim();
return template.content.firstChild;
};
/**
* Every time the function is executed,
* it will delay the execution with the given amount of milliseconds.
*/
if (!Function.prototype.debounce) {
Function.prototype.debounce = function(ms) {
let func = this, timer;
return function(...args) {
timer && clearTimeout(timer);
timer = setTimeout(()=>{
func.apply(this, args)
timer = 0;
}, ms);
};
};
}
/**
* No matter how many times the event is executed,
* the function will be executed only once, after the given amount of milliseconds.
*/
if (!Function.prototype.throttle) {
Function.prototype.throttle = function(ms) {
let func = this, timer;
return function(...args) {
if (!timer) {
timer = setTimeout(()=>{
func.apply(this, args)
timer = 0;
}, ms);
}
};
};
}
})(this); })(this);

View file

@ -70,6 +70,7 @@ config.paths.js = {
name: 'libs.js', name: 'libs.js',
src: [ src: [
'dev/polyfill.js', 'dev/polyfill.js',
'dev/prototype.js',
'node_modules/jquery/dist/jquery.slim.min.js', 'node_modules/jquery/dist/jquery.slim.min.js',
'vendors/jquery-ui/js/jquery-ui-1.12.1.custom.min.js', // custom 'vendors/jquery-ui/js/jquery-ui-1.12.1.custom.min.js', // custom
'vendors/inputosaurus/inputosaurus.js', // custom (modified) 'vendors/inputosaurus/inputosaurus.js', // custom (modified)
@ -80,9 +81,6 @@ config.paths.js = {
'vendors/keymaster/keymaster.js', // custom (modified) 'vendors/keymaster/keymaster.js', // custom (modified)
'vendors/qr.js/qr.min.js', // fixed (license) 'vendors/qr.js/qr.min.js', // fixed (license)
'vendors/bootstrap/js/bootstrap.native.min.js', // fixed 'vendors/bootstrap/js/bootstrap.native.min.js', // fixed
'dev/prototype-date.js',
'dev/prototype-element.js',
'dev/prototype-function.js',
'node_modules/knockout/build/output/knockout-latest.js', 'node_modules/knockout/build/output/knockout-latest.js',
'node_modules/knockout-sortable/build/knockout-sortable.min.js ', 'node_modules/knockout-sortable/build/knockout-sortable.min.js ',
'node_modules/simplestatemanager/dist/ssm.min.js', 'node_modules/simplestatemanager/dist/ssm.min.js',