From ea48f5060bc6ffaf89a7c378caee35950ec98ae7 Mon Sep 17 00:00:00 2001 From: djmaze Date: Wed, 29 Jul 2020 21:49:41 +0200 Subject: [PATCH] isArray to native Array.isArray isUnd(*) to native undefined === * isFunc to native typeof * === 'function' isObject to native typeof * === 'object' microtime() to native Date().getTime(); noop to native ()=>{} noopFalse to native ()=>false noopTrue to native ()=>true boolToAjax to native *?'1':'0' Underscore.js to native --- README.md | 23 +- dev/App/Abstract.js | 35 ++- dev/App/Admin.js | 13 +- dev/App/User.js | 106 +++++---- dev/Common/Booter.js | 1 - dev/Common/Cache.js | 6 +- dev/Common/ClientStorageDriver/Cookie.js | 3 +- .../ClientStorageDriver/LocalStorage.js | 3 +- dev/Common/Events.js | 7 +- dev/Common/Globals.js | 26 +-- dev/Common/HtmlEditor.js | 12 +- dev/Common/Jassl.js | 6 +- dev/Common/Links.js | 8 +- dev/Common/Momentor.js | 32 +-- dev/Common/Plugins.js | 11 +- dev/Common/Selector.js | 21 +- dev/Common/Translator.js | 23 +- dev/Common/Utils.js | 215 +++--------------- dev/Component/Abstract.js | 3 +- dev/Component/AbstractCheckbox.js | 21 +- dev/Component/AbstractInput.js | 12 +- dev/Component/AbstractRadio.js | 7 +- dev/Component/TextArea.js | 3 +- dev/External/ko.js | 18 +- dev/Helper/Message.js | 4 +- dev/Knoin/AbstractModel.js | 14 +- dev/Knoin/AbstractScreen.js | 6 +- dev/Knoin/Knoin.js | 48 ++-- dev/Model/Attachment.js | 4 +- dev/Model/ComposeAttachment.js | 6 +- dev/Model/Message.js | 18 +- dev/Promises/AbstractAjax.js | 7 +- dev/Promises/AbstractBasic.js | 3 +- dev/Promises/User/Populator.js | 16 +- dev/Remote/AbstractAjax.js | 6 +- dev/Remote/User/Ajax.js | 8 +- dev/Screen/AbstractSettings.js | 30 +-- dev/Screen/User/MailBox.js | 14 +- dev/Settings/Admin/Contacts.js | 6 +- dev/Settings/Admin/General.js | 17 +- dev/Settings/Admin/Login.js | 8 +- dev/Settings/Admin/Plugins.js | 3 +- dev/Settings/Admin/Security.js | 14 +- dev/Settings/User/Accounts.js | 3 +- dev/Settings/User/Contacts.js | 3 +- dev/Settings/User/Filters.js | 6 +- dev/Settings/User/Folders.js | 10 +- dev/Settings/User/General.js | 16 +- dev/Settings/User/OpenPgp.js | 7 +- dev/Storage/RainLoop.js | 12 +- dev/Storage/Settings.js | 8 +- dev/Stores/Language.js | 5 +- dev/Stores/Theme.js | 3 +- dev/Stores/User/Folder.js | 4 +- dev/Stores/User/Message.js | 28 ++- dev/Stores/User/Pgp.js | 9 +- dev/View/Popup/Activate.js | 4 +- dev/View/Popup/Ask.js | 5 +- dev/View/Popup/Compose.js | 51 +++-- dev/View/Popup/ComposeOpenPgp.js | 4 +- dev/View/Popup/Contacts.js | 7 +- dev/View/Popup/FolderSystem.js | 30 +-- dev/View/Popup/KeyboardShortcutsHelp.js | 48 ++-- dev/View/Popup/Plugin.js | 8 +- dev/View/User/AbstractSystemDropDown.js | 4 +- dev/View/User/MailBox/FolderList.js | 4 +- dev/View/User/MailBox/MessageList.js | 19 +- dev/View/User/MailBox/MessageView.js | 21 +- dev/bootstrap.js | 29 ++- tasks/config.js | 1 - vendors/underscore/underscore-min.custom.js | 6 - vendors/underscore/underscore.custom.js | 124 ---------- 72 files changed, 551 insertions(+), 775 deletions(-) delete mode 100644 vendors/underscore/underscore-min.custom.js delete mode 100644 vendors/underscore/underscore.custom.js diff --git a/README.md b/README.md index 252815b2e..43983ba61 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,7 @@ This fork has the following changes: * Removed Sentry (Application Monitoring and Error Tracking Software) * Replaced gulp-uglify with gulp-terser * CRLF => LF line endings +* Converted underscore.js to native code * Ongoing removal of old JavaScript code (things are native these days) ### Removal of old JavaScript @@ -62,23 +63,23 @@ Things might work in Edge 15-18, Firefox 47-62 and Chrome 54-68 due to one polyf |js/* |1.14.0 |native | |----------- |--------: |--------: | -|admin.js |2.130.942 |1.355.195 | -|app.js |4.184.455 |3.116.673 | -|boot.js | 671.522 | 109.651 | -|libs.js | 647.614 | 508.324 | +|admin.js |2.130.942 |1.329.869 | +|app.js |4.184.455 |3.092.391 | +|boot.js | 671.522 | 108.460 | +|libs.js | 647.614 | 507.015 | |polyfills.js | 325.834 | 0 | -|TOTAL js |7.960.367 |5.089.843 | +|TOTAL js |7.960.367 |5.037.853 | |js/min/* |1.14.0 |native | |--------------- |--------: |--------: | -|admin.min.js | 252.147 | 176.512 | -|app.min.js | 511.202 | 408.169 | -|boot.min.js | 66.007 | 13.380 | -|libs.min.js | 572.545 | 465.247 | +|admin.min.js | 252.147 | 173.226 | +|app.min.js | 511.202 | 405.035 | +|boot.min.js | 66.007 | 13.240 | +|libs.min.js | 572.545 | 464.161 | |polyfills.min.js | 32.452 | 0 | -|TOTAL js/min |1.434.353 |1.063.308 | +|TOTAL js/min |1.434.353 |1.055.662 | -370.665 bytes is not much, but it feels faster. +378.691 bytes is not much, but it feels faster. ### PHP73 branch diff --git a/dev/App/Abstract.js b/dev/App/Abstract.js index b61b7ef3f..d26799fb0 100644 --- a/dev/App/Abstract.js +++ b/dev/App/Abstract.js @@ -1,5 +1,4 @@ import window from 'window'; -import _ from '_'; import ko from 'ko'; import key from 'key'; import ssm from 'ssm'; @@ -40,19 +39,26 @@ class AbstractApp extends AbstractBoot { Events.pub('window.resize'); }); + var t; Events.sub( 'window.resize', - _.throttle(() => { - const iH = $win.height(), - iW = $win.height(); + ()=>{ + // throttle + if (!t) { + t = setTimeout(()=>{ + const iH = $win.height(), + iW = $win.height(); - if ($win.__sizes[0] !== iH || $win.__sizes[1] !== iW) { - $win.__sizes[0] = iH; - $win.__sizes[1] = iW; + if ($win.__sizes[0] !== iH || $win.__sizes[1] !== iW) { + $win.__sizes[0] = iH; + $win.__sizes[1] = iW; - Events.pub('window.resize.real'); + Events.pub('window.resize.real'); + } + t = 0; + }, Magics.Time50ms); } - }, Magics.Time50ms) + } ); // DEBUG @@ -76,9 +82,14 @@ class AbstractApp extends AbstractBoot { $htmlCL.remove('rl-ctrl-key-pressed'); } }); - const fn = _.debounce(() => { - Events.pub('rl.auto-logout-refresh'); - }, Magics.Time5s); + + var d; + const fn = ()=>{ + // debounce + d && clearTimeout(d); + d = setTimeout(()=>Events.pub('rl.auto-logout-refresh'), Magics.Time5s); + } + $doc.addEventListener('mousemove', fn); $doc.addEventListener('keypress', fn); $doc.addEventListener('click', fn); diff --git a/dev/App/Admin.js b/dev/App/Admin.js index c09f42c39..34a6fccf3 100644 --- a/dev/App/Admin.js +++ b/dev/App/Admin.js @@ -1,12 +1,11 @@ import window from 'window'; -import _ from '_'; import ko from 'ko'; import progressJs from 'progressJs'; import { root } from 'Common/Links'; import { getNotification } from 'Common/Translator'; import { StorageResultType, Notification } from 'Common/Enums'; -import { pInt, isNormal, isArray, isUnd } from 'Common/Utils'; +import { pInt, isNormal } from 'Common/Utils'; import * as Settings from 'Storage/Settings'; @@ -85,10 +84,10 @@ class AdminApp extends AbstractApp { } }); - if (isArray(data.Result.List)) { + if (Array.isArray(data.Result.List)) { list = data.Result.List.map(item => { if (item) { - item.loading = ko.observable(!isUnd(loading[item.file])); + item.loading = ko.observable(loading[item.file] !== undefined); return 'core' === item.type && !item.canBeInstalled ? null : item; } return null; @@ -205,9 +204,9 @@ class AdminApp extends AbstractApp { setHash(root(), true); routeOff(); - _.defer(() => { - window.location.href = '/'; - }); + setTimeout(() => + window.location.href = '/' + , 1); } else { if (Settings.settingsGet('Auth')) { startScreens([SettingsAdminScreen]); diff --git a/dev/App/User.js b/dev/App/User.js index cc8d72d7f..1b68d52b3 100644 --- a/dev/App/User.js +++ b/dev/App/User.js @@ -1,23 +1,19 @@ import window from 'window'; -import _ from '_'; import progressJs from 'progressJs'; import { - noop, - trim, log, - isArray, - isUnd, isNormal, isPosNumeric, isNonEmptyArray, pInt, pString, delegateRunOnDestroy, - mailToHelper, - jassl + mailToHelper } from 'Common/Utils'; +import { jassl } from 'Common/Jassl'; + import { Layout, Capa, @@ -129,10 +125,14 @@ class AppUser extends AbstractApp { this.moveCache = {}; - this.quotaDebounce = _.debounce(this.quota, Magics.Time30s); - this.moveOrDeleteResponseHelper = this.moveOrDeleteResponseHelper.bind(this); + let qd, o = this; + this.quotaDebounce = ()=>{ + // debounce + qd && clearTimeout(qd); + qd = setTimeout(o.quota, Magics.Time30s); + }; - this.messagesMoveTrigger = _.debounce(this.messagesMoveTrigger, 500); + this.moveOrDeleteResponseHelper = this.moveOrDeleteResponseHelper.bind(this); window.setInterval(() => Events.pub('interval.30s'), Magics.Time30s); window.setInterval(() => Events.pub('interval.1m'), Magics.Time1m); @@ -258,7 +258,7 @@ class AppUser extends AbstractApp { } recacheInboxMessageList() { - Remote.messageList(noop, getFolderInboxName(), 0, SettingsStore.messagesPerPage(), '', '', true); + Remote.messageList(()=>{}, getFolderInboxName(), 0, SettingsStore.messagesPerPage(), '', '', true); } /** @@ -290,25 +290,30 @@ class AppUser extends AbstractApp { } messagesMoveTrigger() { - const sTrashFolder = FolderStore.trashFolder(), - sSpamFolder = FolderStore.spamFolder(); + // debounce + const o = this; + o.mt && clearTimeout(o.mt); + o.mt = setTimeout(()=>{ + const sTrashFolder = FolderStore.trashFolder(), + sSpamFolder = FolderStore.spamFolder(); - Object.values(this.moveCache).forEach(item => { - const isSpam = sSpamFolder === item.To, - isTrash = sTrashFolder === item.To, - isHam = !isSpam && sSpamFolder === item.From && getFolderInboxName() === item.To; + Object.values(o.moveCache).forEach(item => { + const isSpam = sSpamFolder === item.To, + isTrash = sTrashFolder === item.To, + isHam = !isSpam && sSpamFolder === item.From && getFolderInboxName() === item.To; - Remote.messagesMove( - this.moveOrDeleteResponseHelper, - item.From, - item.To, - item.Uid, - isSpam ? 'SPAM' : isHam ? 'HAM' : '', - isSpam || isTrash - ); - }); + Remote.messagesMove( + o.moveOrDeleteResponseHelper, + item.From, + item.To, + item.Uid, + isSpam ? 'SPAM' : isHam ? 'HAM' : '', + isSpam || isTrash + ); + }); - this.moveCache = {}; + o.moveCache = {}; + }, 500); } messagesMoveHelper(fromFolderFullNameRaw, toFolderFullNameRaw, uidsForMove) { @@ -336,7 +341,7 @@ class AppUser extends AbstractApp { moveOrDeleteResponseHelper(sResult, oData) { if (StorageResultType.Success === sResult && FolderStore.currentFolder()) { - if (oData && isArray(oData.Result) && 2 === oData.Result.length) { + if (oData && Array.isArray(oData.Result) && 2 === oData.Result.length) { setFolderHash(oData.Result[0], oData.Result[1]); } else { setFolderHash(FolderStore.currentFolderFullNameRaw(), ''); @@ -389,7 +394,7 @@ class AppUser extends AbstractApp { // no default } - bUseFolder = isUnd(bUseFolder) ? true : !!bUseFolder; + bUseFolder = undefined === bUseFolder ? true : !!bUseFolder; if (bUseFolder) { if ( (FolderType.Spam === iDeleteType && UNUSED_OPTION_VALUE === FolderStore.spamFolder()) || @@ -427,12 +432,12 @@ class AppUser extends AbstractApp { * @param {boolean=} bCopy = false */ moveMessagesToFolder(sFromFolderFullNameRaw, aUidForMove, sToFolderFullNameRaw, bCopy) { - if (sFromFolderFullNameRaw !== sToFolderFullNameRaw && isArray(aUidForMove) && aUidForMove.length) { + if (sFromFolderFullNameRaw !== sToFolderFullNameRaw && Array.isArray(aUidForMove) && aUidForMove.length) { const oFromFolder = getFolderFromCacheList(sFromFolderFullNameRaw), oToFolder = getFolderFromCacheList(sToFolderFullNameRaw); if (oFromFolder && oToFolder) { - if (isUnd(bCopy) ? false : !!bCopy) { + if (undefined === bCopy ? false : !!bCopy) { this.messagesCopyHelper(oFromFolder.fullNameRaw, oToFolder.fullNameRaw, aUidForMove); } else { this.messagesMoveHelper(oFromFolder.fullNameRaw, oToFolder.fullNameRaw, aUidForMove); @@ -583,7 +588,7 @@ class AppUser extends AbstractApp { sAccountEmail = AccountStore.email(); let parentEmail = Settings.settingsGet('ParentEmail') || sAccountEmail; - if (isArray(oData.Result.Accounts)) { + if (Array.isArray(oData.Result.Accounts)) { AccountStore.accounts().forEach(oAccount => { counts[oAccount.email] = oAccount.count(); }); @@ -597,12 +602,12 @@ class AppUser extends AbstractApp { ); } - if (isUnd(bBoot) ? false : !!bBoot) { + if (undefined === bBoot ? false : !!bBoot) { setTimeout(() => this.accountsCounts(), 1000 * 5); Events.sub('interval.10m-after5m', () => this.accountsCounts()); } - if (isArray(oData.Result.Identities)) { + if (Array.isArray(oData.Result.Identities)) { delegateRunOnDestroy(IdentityStore.identities()); IdentityStore.identities( @@ -631,7 +636,7 @@ class AppUser extends AbstractApp { Remote.templates((result, data) => { TemplateStore.templates.loading(false); - if (StorageResultType.Success === result && data.Result && isArray(data.Result.Templates)) { + if (StorageResultType.Success === result && data.Result && Array.isArray(data.Result.Templates)) { delegateRunOnDestroy(TemplateStore.templates()); TemplateStore.templates( @@ -650,7 +655,7 @@ class AppUser extends AbstractApp { StorageResultType.Success === result && data && data.Result && - isArray(data.Result) && + Array.isArray(data.Result) && 1 < data.Result.length && isPosNumeric(data.Result[0], true) && isPosNumeric(data.Result[1], true) @@ -665,7 +670,7 @@ class AppUser extends AbstractApp { * @param {Array=} list = [] */ folderInformation(folder, list) { - if (trim(folder)) { + if (folder && folder.trim()) { Remote.folderInformation( (result, data) => { if (StorageResultType.Success === result) { @@ -814,7 +819,7 @@ class AppUser extends AbstractApp { alreadyUnread = 0, rootUids = []; - if (isUnd(messages) || !messages) { + if (undefined === messages || !messages) { messages = MessageStore.messageListChecked(); } @@ -833,7 +838,7 @@ class AppUser extends AbstractApp { folder.messageCountUnread(folder.messageCountUnread() - alreadyUnread); } - Remote.messageSetSeen(noop, sFolderFullNameRaw, rootUids, true); + Remote.messageSetSeen(()=>{}, sFolderFullNameRaw, rootUids, true); break; case MessageSetAction.UnsetSeen: @@ -846,7 +851,7 @@ class AppUser extends AbstractApp { folder.messageCountUnread(folder.messageCountUnread() - alreadyUnread + rootUids.length); } - Remote.messageSetSeen(noop, sFolderFullNameRaw, rootUids, false); + Remote.messageSetSeen(()=>{}, sFolderFullNameRaw, rootUids, false); break; case MessageSetAction.SetFlag: @@ -854,7 +859,7 @@ class AppUser extends AbstractApp { storeMessageFlagsToCacheBySetAction(sFolderFullNameRaw, sSubUid, iSetAction); }); - Remote.messageSetFlagged(noop, sFolderFullNameRaw, rootUids, true); + Remote.messageSetFlagged(()=>{}, sFolderFullNameRaw, rootUids, true); break; case MessageSetAction.UnsetFlag: @@ -862,7 +867,7 @@ class AppUser extends AbstractApp { storeMessageFlagsToCacheBySetAction(sFolderFullNameRaw, sSubUid, iSetAction); }); - Remote.messageSetFlagged(noop, sFolderFullNameRaw, rootUids, false); + Remote.messageSetFlagged(()=>{}, sFolderFullNameRaw, rootUids, false); break; // no default } @@ -878,7 +883,7 @@ class AppUser extends AbstractApp { */ getAutocomplete(query, autocompleteCallback) { Remote.suggestions((result, data) => { - if (StorageResultType.Success === result && data && isArray(data.Result)) { + if (StorageResultType.Success === result && data && Array.isArray(data.Result)) { autocompleteCallback( data.Result.map(item => (item && item[0] ? new EmailModel(item[0], item[1]) : null)).filter(value => !!value) ); @@ -894,7 +899,7 @@ class AppUser extends AbstractApp { */ setExpandedFolder(sFullNameHash, bExpanded) { let aExpandedList = Local.get(ClientSideKeyName.ExpandedFolders); - if (!isArray(aExpandedList)) { + if (!Array.isArray(aExpandedList)) { aExpandedList = []; } @@ -1027,9 +1032,9 @@ class AppUser extends AbstractApp { setHash(root(), true); routeOff(); - _.defer(() => { - window.location.href = customLoginLink; - }); + setTimeout(() => + window.location.href = customLoginLink + , 1); } } @@ -1087,7 +1092,7 @@ class AppUser extends AbstractApp { routeOn(); } - if (jassl && window.crypto && window.crypto.getRandomValues && Settings.capa(Capa.OpenPGP)) { + if (window.crypto && window.crypto.getRandomValues && Settings.capa(Capa.OpenPGP)) { const openpgpCallback = (openpgp) => { PgpStore.openpgp = openpgp; @@ -1156,7 +1161,7 @@ class AppUser extends AbstractApp { }, 1000); setTimeout(() => this.quota(), 5000); - setTimeout(() => Remote.appDelayStart(noop), 35000); + setTimeout(() => Remote.appDelayStart(()=>{}), 35000); Events.sub('rl.auto-logout', () => this.logout()); @@ -1188,7 +1193,8 @@ class AppUser extends AbstractApp { } if (!bMobileDevice) { - _.defer(() => this.initVerticalLayoutResizer(ClientSideKeyName.FolderListSize)); + const o = this; + setTimeout(() => o.initVerticalLayoutResizer(ClientSideKeyName.FolderListSize), 1); } } else { this.logout(); diff --git a/dev/Common/Booter.js b/dev/Common/Booter.js index 28d2492eb..e12c7079e 100644 --- a/dev/Common/Booter.js +++ b/dev/Common/Booter.js @@ -88,7 +88,6 @@ window.__initAppData = data => { const appData = window.__rlah_data(), p = progressJs; if ( - jassl && p && appData && appData.TemplatesLink && diff --git a/dev/Common/Cache.js b/dev/Common/Cache.js index d706d849d..1a55b864e 100644 --- a/dev/Common/Cache.js +++ b/dev/Common/Cache.js @@ -1,5 +1,5 @@ import { MessageSetAction } from 'Common/Enums'; -import { trim, pInt, isArray } from 'Common/Utils'; +import { trim, pInt } from 'Common/Utils'; let FOLDERS_CACHE = {}, FOLDERS_NAME_CACHE = {}, @@ -266,7 +266,7 @@ export function storeMessageFlagsToCache(message) { * @param {Array} flags */ export function storeMessageFlagsToCacheByFolderAndUid(folder, uid, flags) { - if (isArray(flags) && flags.length) { + if (Array.isArray(flags) && flags.length) { setMessageFlagsToCache(folder, uid, flags); } } @@ -280,7 +280,7 @@ export function storeMessageFlagsToCacheBySetAction(folder, uid, setAction) { let unread = 0; const flags = getMessageFlagsFromCache(folder, uid); - if (isArray(flags) && flags.length) { + if (Array.isArray(flags) && flags.length) { if (flags[0]) { unread = 1; } diff --git a/dev/Common/ClientStorageDriver/Cookie.js b/dev/Common/ClientStorageDriver/Cookie.js index ee37525cd..5ae1a6b5a 100644 --- a/dev/Common/ClientStorageDriver/Cookie.js +++ b/dev/Common/ClientStorageDriver/Cookie.js @@ -1,6 +1,5 @@ import window from 'window'; import Cookies from 'js-cookie'; -import { isUnd } from 'Common/Utils'; import { CLIENT_SIDE_STORAGE_INDEX_NAME } from 'Common/Consts'; class CookieDriver { @@ -39,7 +38,7 @@ class CookieDriver { try { const storageResult = Cookies.getJSON(CLIENT_SIDE_STORAGE_INDEX_NAME); - result = storageResult && !isUnd(storageResult[key]) ? storageResult[key] : null; + result = storageResult && undefined !== storageResult[key] ? storageResult[key] : null; } catch (e) {} // eslint-disable-line no-empty return result; diff --git a/dev/Common/ClientStorageDriver/LocalStorage.js b/dev/Common/ClientStorageDriver/LocalStorage.js index 711c342e2..ff266b8f8 100644 --- a/dev/Common/ClientStorageDriver/LocalStorage.js +++ b/dev/Common/ClientStorageDriver/LocalStorage.js @@ -1,5 +1,4 @@ import window from 'window'; -import { isUnd } from 'Common/Utils'; import { isStorageSupported } from 'Storage/RainLoop'; import { CLIENT_SIDE_STORAGE_INDEX_NAME } from 'Common/Consts'; @@ -49,7 +48,7 @@ class LocalStorageDriver { const storageValue = this.s.getItem(CLIENT_SIDE_STORAGE_INDEX_NAME) || null, storageResult = null === storageValue ? null : window.JSON.parse(storageValue); - return storageResult && !isUnd(storageResult[key]) ? storageResult[key] : null; + return storageResult && undefined !== storageResult[key] ? storageResult[key] : null; } catch (e) {} // eslint-disable-line no-empty return null; diff --git a/dev/Common/Events.js b/dev/Common/Events.js index 40c016ee4..8e402976b 100644 --- a/dev/Common/Events.js +++ b/dev/Common/Events.js @@ -1,4 +1,3 @@ -import { isObject, isUnd } from 'Common/Utils'; import * as Plugins from 'Common/Plugins'; const SUBS = {}; @@ -9,7 +8,7 @@ const SUBS = {}; * @param {Object=} context */ export function sub(name, func, context) { - if (isObject(name)) { + if (typeof name === 'object') { context = func || null; func = null; @@ -17,7 +16,7 @@ export function sub(name, func, context) { sub(subName, subFunc, context); }); } else { - if (isUnd(SUBS[name])) { + if (undefined === SUBS[name]) { SUBS[name] = []; } @@ -32,7 +31,7 @@ export function sub(name, func, context) { export function pub(name, args) { Plugins.runHook('rl-pub', [name, args]); - if (!isUnd(SUBS[name])) { + if (undefined !== SUBS[name]) { SUBS[name].forEach(items => { if (items[0]) { items[0].apply(items[1] || null, args || []); diff --git a/dev/Common/Globals.js b/dev/Common/Globals.js index f9f469b63..62cd4a528 100644 --- a/dev/Common/Globals.js +++ b/dev/Common/Globals.js @@ -22,8 +22,6 @@ $hcont .css({ position: 'absolute', left: -5000 }) .appendTo($body); -export const startMicrotime = new window.Date().getTime(); - /** * @type {boolean} */ @@ -48,29 +46,13 @@ export const sUserAgent = /** * @type {boolean} */ -export const bIE = sUserAgent.includes('msie'); - -/** - * @type {boolean} - */ -export const bChrome = sUserAgent.includes('chrome'); - -/** - * @type {boolean} - */ -export const bSafari = !bChrome && sUserAgent.includes('safari'); +export const bSafari = !sUserAgent.includes('chrome') && sUserAgent.includes('safari'); /** * @type {boolean} */ export const bMobileDevice = (/android|iphone|ipod|ipad|blackberry|mobile/i).test(sUserAgent); -/** - * @type {boolean} - */ -export const bIsHttps = - window.document && window.document.location ? 'https:' === window.document.location.protocol : false; - /** * @type {Object} */ @@ -148,12 +130,6 @@ export const htmlEditorLangsMap = { 'zh_tw': 'zh' }; -/** - * @type {boolean} - */ -let bAllowPdfPreview = !bMobileDevice && undefined !== window.navigator.mimeTypes['application/pdf']; - -export { bAllowPdfPreview }; export const VIEW_MODELS = { settings: [], diff --git a/dev/Common/HtmlEditor.js b/dev/Common/HtmlEditor.js index 904702aea..af891c307 100644 --- a/dev/Common/HtmlEditor.js +++ b/dev/Common/HtmlEditor.js @@ -1,5 +1,4 @@ import window from 'window'; -import _ from '_'; import $ from '$'; import { htmlEditorDefaultConfig, htmlEditorLangsMap } from 'Common/Globals'; import { EventKeyCode, Magics } from 'Common/Enums'; @@ -35,7 +34,16 @@ class HtmlEditor { this.element = element; this.$element = $(element); - this.resize = _.throttle(this.resizeEditor.bind(this), 100); + // throttle + var t, o = this; + this.resize = ()=>{ + if (!t) { + t = setTimeout(()=>{ + o.resizeEditor(); + t = 0; + }, 100); + } + }; this.init(); } diff --git a/dev/Common/Jassl.js b/dev/Common/Jassl.js index 0ce622ca6..9ceabb4b2 100644 --- a/dev/Common/Jassl.js +++ b/dev/Common/Jassl.js @@ -8,10 +8,6 @@ import window from 'window'; * @returns {Promise} */ export function jassl(src, async = false) { - if (!window.Promise || !window.Promise.all) { - throw new Error('Promises are not available your environment.'); - } - if (!src) { throw new Error('src should not be empty.'); } @@ -27,7 +23,7 @@ export function jassl(src, async = false) { reject(new Error(src)); }; - element.async = true === async; + element.async = !!async; element.src = src; window.document.body.appendChild(element); diff --git a/dev/Common/Links.js b/dev/Common/Links.js index b87af628c..4717a0f87 100644 --- a/dev/Common/Links.js +++ b/dev/Common/Links.js @@ -1,5 +1,5 @@ import window from 'window'; -import { pString, pInt, isUnd, isNormal, trim, encodeURIComponent } from 'Common/Utils'; +import { pString, pInt, isNormal, trim } from 'Common/Utils'; import * as Settings from 'Storage/Settings'; const ROOT = './', @@ -58,7 +58,7 @@ export function rootUser() { * @returns {string} */ export function attachmentRaw(type, download, customSpecSuffix) { - customSpecSuffix = isUnd(customSpecSuffix) ? AUTH_PREFIX : customSpecSuffix; + customSpecSuffix = undefined === customSpecSuffix ? AUTH_PREFIX : customSpecSuffix; return ( SERVER_PREFIX + '/Raw/' + @@ -160,7 +160,7 @@ export function append() { * @returns {string} */ export function change(email) { - return serverRequest('Change') + encodeURIComponent(email) + '/'; + return serverRequest('Change') + window.encodeURIComponent(email) + '/'; } /** @@ -204,7 +204,7 @@ export function messageDownloadLink(requestHash) { * @returns {string} */ export function avatarLink(email) { - return SERVER_PREFIX + '/Raw/0/Avatar/' + encodeURIComponent(email) + '/'; + return SERVER_PREFIX + '/Raw/0/Avatar/' + window.encodeURIComponent(email) + '/'; } /** diff --git a/dev/Common/Momentor.js b/dev/Common/Momentor.js index 1b067daa7..93be83414 100644 --- a/dev/Common/Momentor.js +++ b/dev/Common/Momentor.js @@ -1,5 +1,4 @@ import window from 'window'; -import _ from '_'; import $ from '$'; import moment from 'moment'; import { i18n } from 'Common/Translator'; @@ -7,21 +6,22 @@ import { i18n } from 'Common/Translator'; let _moment = null; let _momentNow = 0; -const updateMomentNow = _.debounce( - () => { +var d, du; +const updateMomentNow = ()=>{ + // leading debounce + if (!d) { + d = setTimeout(()=>d=0, 500); _moment = moment(); - }, - 500, - true -); + } +}; -const updateMomentNowUnix = _.debounce( - () => { +const updateMomentNowUnix = ()=>{ + // leading debounce + if (!du) { + du = setTimeout(()=>du=0, 500); _momentNow = moment().unix(); - }, - 500, - true -); + } +}; /** * @returns {moment} @@ -147,9 +147,9 @@ export function momentToNode(element) { * @returns {void} */ export function reload() { - _.defer(() => { + setTimeout(() => $('.moment', window.document).each((index, item) => { momentToNode(item); - }); - }); + }) + , 1); } diff --git a/dev/Common/Plugins.js b/dev/Common/Plugins.js index ba46b2c12..22b28128a 100644 --- a/dev/Common/Plugins.js +++ b/dev/Common/Plugins.js @@ -1,4 +1,3 @@ -import { isFunc, isArray, isUnd } from 'Common/Utils'; import { data as GlobalsData } from 'Common/Globals'; import * as Settings from 'Storage/Settings'; @@ -11,8 +10,8 @@ const SIMPLE_HOOKS = {}, * @param {Function} callback */ export function addHook(name, callback) { - if (isFunc(callback)) { - if (!isArray(SIMPLE_HOOKS[name])) { + if (typeof callback === 'function') { + if (!Array.isArray(SIMPLE_HOOKS[name])) { SIMPLE_HOOKS[name] = []; } @@ -25,7 +24,7 @@ export function addHook(name, callback) { * @param {Array=} args = [] */ export function runHook(name, args = []) { - if (isArray(SIMPLE_HOOKS[name])) { + if (Array.isArray(SIMPLE_HOOKS[name])) { SIMPLE_HOOKS[name].forEach(callback => { callback(...args); }); @@ -89,6 +88,6 @@ export function runSettingsViewModelHooks(admin) { */ export function settingsGet(pluginSection, name) { let plugins = Settings.settingsGet('Plugins'); - plugins = plugins && !isUnd(plugins[pluginSection]) ? plugins[pluginSection] : null; - return plugins ? (isUnd(plugins[name]) ? null : plugins[name]) : null; + plugins = plugins && undefined !== plugins[pluginSection] ? plugins[pluginSection] : null; + return plugins ? (undefined === plugins[name] ? null : plugins[name]) : null; } diff --git a/dev/Common/Selector.js b/dev/Common/Selector.js index ad6553323..2401cbfbc 100644 --- a/dev/Common/Selector.js +++ b/dev/Common/Selector.js @@ -1,9 +1,7 @@ import $ from '$'; -import _ from '_'; import key from 'key'; import ko from 'ko'; import { EventKeyCode } from 'Common/Enums'; -import { isArray, noop, noopTrue } from 'Common/Utils'; class Selector { list; @@ -56,7 +54,12 @@ class Selector { this.focusedItem = koFocusedItem || ko.observable(null); this.selectedItem = koSelectedItem || ko.observable(null); - this.itemSelectedThrottle = _.debounce(this.itemSelected.bind(this), 300); + var d, o = this; + this.itemSelectedThrottle = (item)=>{ + // debounce + d && clearTimeout(d); + d = setTimeout(()=>o.itemSelected(item), 300); + }; this.listChecked.subscribe((items) => { if (items.length) { @@ -109,7 +112,7 @@ class Selector { this.list.subscribe( (items) => { - if (isArray(items)) { + if (Array.isArray(items)) { items.forEach(item => { if (item) { const uid = this.getItemUid(item); @@ -147,7 +150,7 @@ class Selector { this.focusedItem(null); this.selectedItem(null); - if (isArray(aItems)) { + if (Array.isArray(aItems)) { len = aCheckedCache.length; aItems.forEach(item => { @@ -240,10 +243,10 @@ class Selector { itemSelected(item) { if (this.isListChecked()) { if (!item) { - (this.oCallbacks.onItemSelect || noop)(item || null); + (this.oCallbacks.onItemSelect || (()=>{}))(item || null); } } else if (item) { - (this.oCallbacks.onItemSelect || noop)(item); + (this.oCallbacks.onItemSelect || (()=>{}))(item); } } @@ -351,14 +354,14 @@ class Selector { * @returns {boolean} */ autoSelect() { - return !!(this.oCallbacks.onAutoSelect || noopTrue)(); + return !!(this.oCallbacks.onAutoSelect || (()=>true))(); } /** * @param {boolean} up */ doUpUpOrDownDown(up) { - (this.oCallbacks.onUpUpOrDownDown || noopTrue)(!!up); + (this.oCallbacks.onUpUpOrDownDown || (()=>true))(!!up); } /** diff --git a/dev/Common/Translator.js b/dev/Common/Translator.js index 04b435dc7..a63f6e129 100644 --- a/dev/Common/Translator.js +++ b/dev/Common/Translator.js @@ -1,9 +1,8 @@ import window from 'window'; -import _ from '_'; import $ from '$'; import ko from 'ko'; import { Notification, UploadErrorCode } from 'Common/Enums'; -import { pInt, isUnd, microtime } from 'Common/Utils'; +import { pInt } from 'Common/Utils'; import { $html, $htmlCL } from 'Common/Globals'; import { reload as momentorReload } from 'Common/Momentor'; import { langLink } from 'Common/Links'; @@ -94,11 +93,11 @@ export function i18n(key, valueList, defaulValue) { let valueName = '', result = I18N_DATA[key]; - if (isUnd(result)) { - result = isUnd(defaulValue) ? key : defaulValue; + if (undefined === result) { + result = undefined === defaulValue ? key : defaulValue; } - if (!isUnd(valueList) && null !== valueList) { + if (undefined !== valueList && null !== valueList) { for (valueName in valueList) { if (Object.prototype.hasOwnProperty.call(valueList, valueName)) { result = result.replace('%' + valueName + '%', valueList[valueName]); @@ -138,11 +137,11 @@ const i18nToNode = (element) => { * @param {boolean=} animate = false */ export function i18nToNodes(elements) { - _.defer(() => { + setTimeout(() => $('[data-i18n]', elements).each((index, item) => { i18nToNode(item); - }); - }); + }) + , 1); } const reloadData = () => { @@ -203,8 +202,8 @@ export function getNotification(code, message = '', defCode = null) { } defCode = defCode ? window.parseInt(defCode, 10) || 0 : 0; - return isUnd(I18N_NOTIFICATION_DATA[code]) - ? defCode && isUnd(I18N_NOTIFICATION_DATA[defCode]) + return undefined === I18N_NOTIFICATION_DATA[code] + ? defCode && undefined === I18N_NOTIFICATION_DATA[defCode] ? I18N_NOTIFICATION_DATA[defCode] : '' : I18N_NOTIFICATION_DATA[code]; @@ -259,7 +258,7 @@ export function getUploadErrorDescByCode(code) { * @param {string} language */ export function reload(admin, language) { - const start = microtime(); + const start = new Date().getTime(); $htmlCL.add('rl-changing-language'); @@ -292,7 +291,7 @@ export function reload(admin, language) { resolve(); }, - 500 < microtime() - start ? 1 : 500 + 500 < (new Date().getTime()) - start ? 1 : 500 ); }); }); diff --git a/dev/Common/Utils.js b/dev/Common/Utils.js index a34a74ed8..e23de6b52 100644 --- a/dev/Common/Utils.js +++ b/dev/Common/Utils.js @@ -1,22 +1,15 @@ import window from 'window'; import $ from '$'; -import _ from '_'; import ko from 'ko'; import Autolinker from 'Autolinker'; import { $win, $div, $hcont, dropdownVisibility, data as GlobalsData } from 'Common/Globals'; -import { ComposeType, EventKeyCode, SaveSettingsStep, FolderType } from 'Common/Enums'; +import { ComposeType, SaveSettingsStep, FolderType } from 'Common/Enums'; import { Mime } from 'Common/Mime'; -import { jassl } from 'Common/Jassl'; const trim = $.trim; const isArray = Array.isArray; -const isObject = v => typeof v === 'object'; -const isFunc = v => typeof v === 'function'; -const isUnd = v => undefined === v; -const noop = () => {}; // eslint-disable-line no-empty-function -const noopTrue = () => true; -const noopFalse = () => false; +const decodeURIComponent = component => window.decodeURIComponent(component); var htmlspecialchars = ((de,se,gt,lt,sq,dq,bt) => { return (str, quote_style = 3, double_encode = true) => { @@ -30,23 +23,14 @@ var htmlspecialchars = ((de,se,gt,lt,sq,dq,bt) => { }; })(/&/g,/&(?![\w#]+;)/gi,//g,/'/g,/"/g,/`/g); -export { trim, isArray, isObject, isFunc, isUnd, noop, noopTrue, noopFalse, jassl }; - -/** - * @param {Function} func - */ -export function silentTryCatch(func) { - try { - func(); - } catch (e) {} // eslint-disable-line no-empty -} +export { trim }; /** * @param {*} value * @returns {boolean} */ export function isNormal(value) { - return !isUnd(value) && null !== value; + return undefined !== value && null !== value; } /** @@ -80,22 +64,6 @@ export function pString(value) { return isNormal(value) ? '' + value : ''; } -/** - * @param {*} value - * @returns {boolean} - */ -export function pBool(value) { - return !!value; -} - -/** - * @param {*} value - * @returns {string} - */ -export function boolToAjax(value) { - return value ? '1' : '0'; -} - /** * @param {*} values * @returns {boolean} @@ -104,38 +72,6 @@ export function isNonEmptyArray(values) { return isArray(values) && values.length; } -/** - * @param {string} component - * @returns {string} - */ -export function encodeURIComponent(component) { - return window.encodeURIComponent(component); -} - -/** - * @param {string} component - * @returns {string} - */ -export function decodeURIComponent(component) { - return window.decodeURIComponent(component); -} - -/** - * @param {string} url - * @returns {string} - */ -export function decodeURI(url) { - return window.decodeURI(url); -} - -/** - * @param {string} url - * @returns {string} - */ -export function encodeURI(url) { - return window.encodeURI(url); -} - /** * @param {string} queryString * @returns {Object} @@ -210,28 +146,16 @@ export function splitPlainText(text, len = 100) { return prefix + result; } -const timeOutAction = (function() { +const timeOutAction = (() => { const timeOuts = {}; return (action, fFunction, timeOut) => { - timeOuts[action] = isUnd(timeOuts[action]) ? 0 : timeOuts[action]; + timeOuts[action] = undefined === timeOuts[action] ? 0 : timeOuts[action]; window.clearTimeout(timeOuts[action]); timeOuts[action] = window.setTimeout(fFunction, timeOut); }; })(); -const timeOutActionSecond = (function() { - const timeOuts = {}; - return (action, fFunction, timeOut) => { - if (!timeOuts[action]) { - timeOuts[action] = window.setTimeout(() => { - fFunction(); - timeOuts[action] = 0; - }, timeOut); - } - }; -})(); - -export { timeOutAction, timeOutActionSecond }; +export { timeOutAction }; /** * @param {any} m @@ -247,7 +171,7 @@ export function deModule(m) { export function inFocus() { try { if (window.document.activeElement) { - if (isUnd(window.document.activeElement.__inFocusCache)) { + if (undefined === window.document.activeElement.__inFocusCache) { window.document.activeElement.__inFocusCache = $(window.document.activeElement).is( 'input,textarea,iframe,.cke_editable' ); @@ -395,36 +319,6 @@ export function delegateRun(object, methodName, params, delay = 0) { } } -/** - * @param {?} event - */ -export function killCtrlACtrlS(event) { - event = event || window.event; - if (event && event.ctrlKey && !event.shiftKey && !event.altKey) { - const key = event.keyCode || event.which; - if (key === EventKeyCode.S) { - event.preventDefault(); - return; - } else if (key === EventKeyCode.A) { - const sender = event.target || event.srcElement; - if ( - sender && - ('true' === '' + sender.contentEditable || (sender.tagName && sender.tagName.match(/INPUT|TEXTAREA/i))) - ) { - return; - } - - if (window.getSelection) { - window.getSelection().removeAllRanges(); - } else if (window.document.selection && window.document.selection.clear) { - window.document.selection.clear(); - } - - event.preventDefault(); - } - } -} - /** * @param {(Object|null|undefined)} context * @param {Function} fExecute @@ -440,11 +334,11 @@ export function createCommandLegacy(context, fExecute, fCanExecute = true) { return false; }; - fResult = fExecute ? fNonEmpty : noop; + fResult = fExecute ? fNonEmpty : ()=>{}; fResult.enabled = ko.observable(true); fResult.isCommand = true; - if (isFunc(fCanExecute)) { + if (typeof fCanExecute === 'function') { fResult.canExecute = ko.computed(() => fResult && fResult.enabled() && fCanExecute.call(context)); } else { fResult.canExecute = ko.computed(() => fResult && fResult.enabled() && !!fCanExecute); @@ -470,28 +364,6 @@ export const convertThemeName = theme => { ); }; -/** - * @param {string} name - * @returns {string} - */ -export function quoteName(name) { - return name.replace(/["]/g, '\\"'); -} - -/** - * @returns {number} - */ -export function microtime() { - return new window.Date().getTime(); -} - -/** - * @returns {number} - */ -export function timestamp() { - return window.Math.round(microtime() / 1000); -} - /** * * @param {string} language @@ -525,7 +397,7 @@ export function draggablePlace() { * @returns {void} */ export function defautOptionsAfterRender(domItem, item) { - if (item && !isUnd(item.disabled) && domItem) { + if (item && undefined !== item.disabled && domItem) { $(domItem) .toggleClass('disabled', item.disabled) .prop('disabled', item.disabled); @@ -886,7 +758,7 @@ export function folderListOptionsBuilder( const sDeepPrefix = '\u00A0\u00A0\u00A0'; - bBuildUnvisible = isUnd(bBuildUnvisible) ? false : !!bBuildUnvisible; + bBuildUnvisible = undefined === bBuildUnvisible ? false : !!bBuildUnvisible; bSystem = !isNormal(bSystem) ? 0 < aSystem.length : bSystem; iUnDeep = !isNormal(iUnDeep) ? 0 : iUnDeep; fDisableCallback = isNormal(fDisableCallback) ? fDisableCallback : null; @@ -1016,9 +888,14 @@ export function selectElement(element) { } } -export const detectDropdownVisibility = _.debounce(() => { - dropdownVisibility(!!GlobalsData.aBootstrapDropdowns.find(item => item.hasClass('open'))); -}, 50); +var dv; +export const detectDropdownVisibility = ()=>{ + // leading debounce + dv && clearTimeout(dv); + dv = setTimeout(()=> + dropdownVisibility(!!GlobalsData.aBootstrapDropdowns.find(item => item.hasClass('open'))) + , 50); +}; /** * @param {boolean=} delay = false @@ -1055,30 +932,6 @@ export function getConfigurationFromScriptTag(configuration) { return {}; } -/** - * @param {mixed} mPropOrValue - * @param {mixed} value - */ -export function disposeOne(propOrValue, value) { - const disposable = value || propOrValue; - if (disposable && 'function' === typeof disposable.dispose) { - disposable.dispose(); - } -} - -/** - * @param {Object} object - */ -export function disposeObject(object) { - if (object) { - if (isArray(object.disposables)) { - object.disposables.forEach(disposeOne); - } - - ko.utils.objectForEach(object, disposeOne); - } -} - /** * @param {Object|Array} objectOrObjects * @returns {void} @@ -1102,7 +955,7 @@ export function delegateRunOnDestroy(objectOrObjects) { */ export function appendStyles($styleTag, css) { if ($styleTag && $styleTag[0]) { - if ($styleTag[0].styleSheet && !isUnd($styleTag[0].styleSheet.cssText)) { + if ($styleTag[0].styleSheet && undefined !== $styleTag[0].styleSheet.cssText) { $styleTag[0].styleSheet.cssText = css; } else { $styleTag.text(css); @@ -1122,7 +975,7 @@ let __themeTimer = 0, * @param {function=} themeTrigger = noop * @returns {void} */ -export function changeTheme(value, themeTrigger = noop) { +export function changeTheme(value, themeTrigger = ()=>{}) { const themeLink = $('#app-theme-link'), clearTimer = () => { __themeTimer = window.setTimeout(() => themeTrigger(SaveSettingsStep.Idle), 1000); @@ -1292,7 +1145,7 @@ export function mimeContentType(fileName) { } ext = getFileExtension(fileName); - if (ext && ext.length && !isUnd(Mime[ext])) { + if (ext && ext.length && undefined !== Mime[ext]) { result = Mime[ext]; } @@ -1384,7 +1237,7 @@ export function mailToHelper(mailToUrl, PopupComposeViewModel) { params = simpleQueryParser(query); - if (!isUnd(params.to)) { + if (undefined !== params.to) { to = EmailModel.parseEmailLine(decodeURIComponent(email + ',' + params.to)); to = Object.values( to.reduce((result, value) => { @@ -1404,11 +1257,11 @@ export function mailToHelper(mailToUrl, PopupComposeViewModel) { to = EmailModel.parseEmailLine(email); } - if (!isUnd(params.cc)) { + if (undefined !== params.cc) { cc = EmailModel.parseEmailLine(decodeURIComponent(params.cc)); } - if (!isUnd(params.bcc)) { + if (undefined !== params.bcc) { bcc = EmailModel.parseEmailLine(decodeURIComponent(params.bcc)); } @@ -1418,8 +1271,8 @@ export function mailToHelper(mailToUrl, PopupComposeViewModel) { to, cc, bcc, - isUnd(params.subject) ? null : pString(decodeURIComponent(params.subject)), - isUnd(params.body) ? null : plainToHtml(pString(decodeURIComponent(params.body))) + undefined === params.subject ? null : pString(decodeURIComponent(params.subject)), + undefined === params.body ? null : plainToHtml(pString(decodeURIComponent(params.body))) ]); return true; @@ -1445,15 +1298,15 @@ export function domReady(fn) { // } } -export const windowResize = _.debounce((timeout) => { - if (isUnd(timeout) || null === timeout) { +var wr; +export const windowResize = timeout => { + wr && clearTimeout(wr); + if (undefined === timeout || null === timeout) { $win.trigger('resize'); } else { - window.setTimeout(() => { - $win.trigger('resize'); - }, timeout); + wr = setTimeout(()=>$win.trigger('resize'), timeout); } -}, 50); +}; /** * @returns {void} diff --git a/dev/Component/Abstract.js b/dev/Component/Abstract.js index bd4b53602..5dda0845d 100644 --- a/dev/Component/Abstract.js +++ b/dev/Component/Abstract.js @@ -1,7 +1,6 @@ import $ from '$'; import ko from 'ko'; -import { isUnd } from 'Common/Utils'; import { i18nToNodes } from 'Common/Translator'; class AbstractComponent { @@ -34,7 +33,7 @@ const componentExportHelper = (ClassObject, templateID = '') => ({ i18nToNodes(params.element); - if (!isUnd(params.inline) && ko.unwrap(params.inline)) { + if (undefined !== params.inline && ko.unwrap(params.inline)) { params.element.css('display', 'inline-block'); } } diff --git a/dev/Component/AbstractCheckbox.js b/dev/Component/AbstractCheckbox.js index 0663dbc89..95fa0af95 100644 --- a/dev/Component/AbstractCheckbox.js +++ b/dev/Component/AbstractCheckbox.js @@ -1,5 +1,4 @@ import ko from 'ko'; -import { isUnd } from 'Common/Utils'; import { AbstractComponent } from 'Component/Abstract'; class AbstractCheckbox extends AbstractComponent { @@ -10,27 +9,27 @@ class AbstractCheckbox extends AbstractComponent { super(); this.value = params.value; - if (isUnd(this.value) || !this.value.subscribe) { - this.value = ko.observable(isUnd(this.value) ? false : !!this.value); + if (undefined === this.value || !this.value.subscribe) { + this.value = ko.observable(undefined === this.value ? false : !!this.value); } this.enable = params.enable; - if (isUnd(this.enable) || !this.enable.subscribe) { - this.enable = ko.observable(isUnd(this.enable) ? true : !!this.enable); + if (undefined === this.enable || !this.enable.subscribe) { + this.enable = ko.observable(undefined === this.enable ? true : !!this.enable); } this.disable = params.disable; - if (isUnd(this.disable) || !this.disable.subscribe) { - this.disable = ko.observable(isUnd(this.disable) ? false : !!this.disable); + if (undefined === this.disable || !this.disable.subscribe) { + this.disable = ko.observable(undefined === this.disable ? false : !!this.disable); } this.label = params.label || ''; - this.inline = isUnd(params.inline) ? false : params.inline; + this.inline = undefined === params.inline ? false : params.inline; - this.readOnly = isUnd(params.readOnly) ? false : !!params.readOnly; - this.inverted = isUnd(params.inverted) ? false : !!params.inverted; + this.readOnly = undefined === params.readOnly ? false : !!params.readOnly; + this.inverted = undefined === params.inverted ? false : !!params.inverted; - this.labeled = !isUnd(params.label); + this.labeled = undefined !== params.label; this.labelAnimated = !!params.labelAnimated; } diff --git a/dev/Component/AbstractInput.js b/dev/Component/AbstractInput.js index d3bf945d8..e2679361d 100644 --- a/dev/Component/AbstractInput.js +++ b/dev/Component/AbstractInput.js @@ -1,5 +1,5 @@ import ko from 'ko'; -import { isUnd, trim, pInt } from 'Common/Utils'; +import { trim, pInt } from 'Common/Utils'; import { SaveSettingsStep } from 'Common/Enums'; import { AbstractComponent } from 'Component/Abstract'; @@ -14,13 +14,13 @@ class AbstractInput extends AbstractComponent { this.size = params.size || 0; this.label = params.label || ''; this.preLabel = params.preLabel || ''; - this.enable = isUnd(params.enable) ? true : params.enable; + this.enable = undefined === params.enable ? true : params.enable; this.trigger = params.trigger && params.trigger.subscribe ? params.trigger : null; this.placeholder = params.placeholder || ''; - this.labeled = !isUnd(params.label); - this.preLabeled = !isUnd(params.preLabel); - this.triggered = !isUnd(params.trigger) && !!this.trigger; + this.labeled = undefined !== params.label; + this.preLabeled = undefined !== params.preLabel; + this.triggered = undefined !== params.trigger && !!this.trigger; this.classForTrigger = ko.observable(''); @@ -30,7 +30,7 @@ class AbstractInput extends AbstractComponent { return (0 < size ? 'span' + size : '') + suffixValue; }); - if (!isUnd(params.width) && params.element) { + if (undefined !== params.width && params.element) { params.element.find('input,select,textarea').css('width', params.width); } diff --git a/dev/Component/AbstractRadio.js b/dev/Component/AbstractRadio.js index 28334400a..8a70034b3 100644 --- a/dev/Component/AbstractRadio.js +++ b/dev/Component/AbstractRadio.js @@ -1,5 +1,4 @@ import ko from 'ko'; -import { isUnd } from 'Common/Utils'; import { AbstractComponent } from 'Component/Abstract'; class AbstractRadio extends AbstractComponent { @@ -12,12 +11,12 @@ class AbstractRadio extends AbstractComponent { this.values = ko.observableArray([]); this.value = params.value; - if (isUnd(this.value) || !this.value.subscribe) { + if (undefined === this.value || !this.value.subscribe) { this.value = ko.observable(''); } - this.inline = isUnd(params.inline) ? false : params.inline; - this.readOnly = isUnd(params.readOnly) ? false : !!params.readOnly; + this.inline = undefined === params.inline ? false : params.inline; + this.readOnly = undefined === params.readOnly ? false : !!params.readOnly; if (params.values) { this.values(Object.entries(params.values).map((label, value) => ({ label: label, value: value }))); diff --git a/dev/Component/TextArea.js b/dev/Component/TextArea.js index 478f56bc2..0fe89399d 100644 --- a/dev/Component/TextArea.js +++ b/dev/Component/TextArea.js @@ -1,4 +1,3 @@ -import { isUnd } from 'Common/Utils'; import { componentExportHelper } from 'Component/Abstract'; import { AbstractInput } from 'Component/AbstractInput'; @@ -12,7 +11,7 @@ class TextAreaComponent extends AbstractInput { super(params); this.rows = params.rows || DEFAULT_ROWS; - this.spellcheck = isUnd(params.spellcheck) ? false : !!params.spellcheck; + this.spellcheck = undefined === params.spellcheck ? false : !!params.spellcheck; } } diff --git a/dev/External/ko.js b/dev/External/ko.js index 7d2cfca8e..362884a5c 100644 --- a/dev/External/ko.js +++ b/dev/External/ko.js @@ -1,5 +1,4 @@ import window from 'window'; -import _ from '_'; import $ from '$'; import Opentip from 'Opentip'; import Pikaday from 'pikaday'; @@ -81,14 +80,21 @@ ko.bindingHandlers.json = { ko.bindingHandlers.scrollerShadows = { init: (element) => { + var t; const limit = 8, $el = $(element), cont = $el.find('[data-scroller-shadows-content]')[0] || null, - fFunc = _.throttle(() => { - $el - .toggleClass('scroller-shadow-top', limit < cont.scrollTop) - .toggleClass('scroller-shadow-bottom', cont.scrollTop + limit < cont.scrollHeight - cont.clientHeight); - }, 100); + // throttle + fFunc = ()=>{ + if (!t) { + t = setTimeout(()=>{ + $el + .toggleClass('scroller-shadow-top', limit < cont.scrollTop) + .toggleClass('scroller-shadow-bottom', cont.scrollTop + limit < cont.scrollHeight - cont.clientHeight); + t = 0; + }, 100); + } + }; if (cont) { $(cont).on('scroll resize', fFunc); diff --git a/dev/Helper/Message.js b/dev/Helper/Message.js index 8dd5e25e5..915ded2d7 100644 --- a/dev/Helper/Message.js +++ b/dev/Helper/Message.js @@ -1,4 +1,4 @@ -import { isNonEmptyArray, isUnd } from 'Common/Utils'; +import { isNonEmptyArray } from 'Common/Utils'; import { EmailModel } from 'Model/Email'; /** @@ -59,7 +59,7 @@ export function emailArrayFromJson(json) { export function replyHelper(inputEmails, unic, localEmails) { if (inputEmails) { inputEmails.forEach(email => { - if (isUnd(unic[email.email])) { + if (undefined === unic[email.email]) { unic[email.email] = true; localEmails.push(email); } diff --git a/dev/Knoin/AbstractModel.js b/dev/Knoin/AbstractModel.js index 1ed79a667..97c5d1ff4 100644 --- a/dev/Knoin/AbstractModel.js +++ b/dev/Knoin/AbstractModel.js @@ -1,4 +1,9 @@ -import { isArray, disposeObject } from 'Common/Utils'; + +function disposeOne(disposable) { + if (disposable && 'function' === typeof disposable.dispose) { + disposable.dispose(); + } +} export class AbstractModel { sModelName = ''; @@ -12,7 +17,7 @@ export class AbstractModel { } regDisposables(value) { - if (isArray(value)) { + if (Array.isArray(value)) { value.forEach((item) => { this.disposables.push(item); }); @@ -22,6 +27,9 @@ export class AbstractModel { } onDestroy() { - disposeObject(this); + if (Array.isArray(this.disposables)) { + this.disposables.forEach(disposeOne); + } + Object.values(this).forEach(disposeOne); } } diff --git a/dev/Knoin/AbstractScreen.js b/dev/Knoin/AbstractScreen.js index 7de0d3686..3cfab032a 100644 --- a/dev/Knoin/AbstractScreen.js +++ b/dev/Knoin/AbstractScreen.js @@ -1,5 +1,5 @@ import crossroads from 'crossroads'; -import { isArray, isNonEmptyArray, noop } from 'Common/Utils'; +import { isNonEmptyArray } from 'Common/Utils'; export class AbstractScreen { oCross = null; @@ -8,7 +8,7 @@ export class AbstractScreen { constructor(screenName, viewModels = []) { this.sScreenName = screenName; - this.aViewModels = isArray(viewModels) ? viewModels : []; + this.aViewModels = Array.isArray(viewModels) ? viewModels : []; } /** @@ -48,7 +48,7 @@ export class AbstractScreen { const routes = this.routes(); if (isNonEmptyArray(routes)) { - fMatcher = (this.onRoute || noop).bind(this); + fMatcher = (this.onRoute || (()=>{})).bind(this); route = crossroads.create(); routes.forEach((item) => { diff --git a/dev/Knoin/Knoin.js b/dev/Knoin/Knoin.js index 88609868b..5cf176602 100644 --- a/dev/Knoin/Knoin.js +++ b/dev/Knoin/Knoin.js @@ -1,4 +1,3 @@ -import _ from '_'; import $ from '$'; import ko from 'ko'; import hasher from 'hasher'; @@ -8,7 +7,7 @@ import { Magics } from 'Common/Enums'; import { runHook } from 'Common/Plugins'; import { $htmlCL, VIEW_MODELS, popupVisibilityNames } from 'Common/Globals'; -import { isArray, isUnd, pString, log, isFunc, createCommandLegacy, delegateRun, isNonEmptyArray } from 'Common/Utils'; +import { pString, log, createCommandLegacy, delegateRun, isNonEmptyArray } from 'Common/Utils'; let currentScreen = null, defaultScreenName = ''; @@ -95,7 +94,7 @@ export function routeOn() { * @returns {?Object} */ export function screen(screenName) { - return screenName && !isUnd(SCREENS[screenName]) ? SCREENS[screenName] : null; + return screenName && undefined !== SCREENS[screenName] ? SCREENS[screenName] : null; } /** @@ -317,7 +316,7 @@ export function screenOnRoute(screenName, subPart) { delegateRun(vmScreen, 'onBuild'); } - _.defer(() => { + setTimeout(() => { // hide screen if (currentScreen && !isSameScreen) { delegateRun(currentScreen, 'onHide'); @@ -389,7 +388,7 @@ export function screenOnRoute(screenName, subPart) { if (cross) { cross.parse(subPart); } - }); + }, 1); } } } @@ -470,7 +469,7 @@ function viewDecorator({ name, type, templateID }) { return (target) => { if (target) { if (name) { - if (isArray(name)) { + if (Array.isArray(name)) { target.__names = name; } else { target.__names = [name]; @@ -509,7 +508,7 @@ function commandDecorator(canExecute = true) { } const value = descriptor.value || descriptor.initializer(), - normCanExecute = isFunc(canExecute) ? canExecute : () => !!canExecute; + normCanExecute = typeof canExecute === 'function' ? canExecute : () => !!canExecute; descriptor.value = function(...args) { if (normCanExecute.call(this, this)) { @@ -531,23 +530,30 @@ function commandDecorator(canExecute = true) { * @returns {Function} */ function settingsMenuKeysHandler($items) { - return _.throttle((event, handler) => { - const up = handler && 'up' === handler.shortcut; + // throttle + var t; + return (event, handler)=>{ + if (!t) { + t = setTimeout(()=>{ + const up = handler && 'up' === handler.shortcut; - if (event && $items.length) { - let index = $items.index($items.filter('.selected')); - if (up && 0 < index) { - index -= 1; - } else if (!up && index < $items.length - 1) { - index += 1; - } + if (event && $items.length) { + let index = $items.index($items.filter('.selected')); + if (up && 0 < index) { + index -= 1; + } else if (!up && index < $items.length - 1) { + index += 1; + } - const resultHash = $items.eq(index).attr('href'); - if (resultHash) { - setHash(resultHash, false, true); - } + const resultHash = $items.eq(index).attr('href'); + if (resultHash) { + setHash(resultHash, false, true); + } + } + t = 0; + }, Magics.Time200ms); } - }, Magics.Time200ms); + }; } export { diff --git a/dev/Model/Attachment.js b/dev/Model/Attachment.js index 98db93347..fd46ca663 100644 --- a/dev/Model/Attachment.js +++ b/dev/Model/Attachment.js @@ -2,7 +2,7 @@ import window from 'window'; import ko from 'ko'; import { FileType } from 'Common/Enums'; -import { bAllowPdfPreview } from 'Common/Globals'; +import { bMobileDevice } from 'Common/Globals'; import { trim, pInt, isNonEmptyArray, getFileExtension, friendlySize } from 'Common/Utils'; import { attachmentDownload, @@ -16,6 +16,8 @@ import { AbstractModel } from 'Knoin/AbstractModel'; import Audio from 'Common/Audio'; +const bAllowPdfPreview = !bMobileDevice && undefined !== window.navigator.mimeTypes['application/pdf']; + /** * @param {string} sExt * @param {string} sMimeType diff --git a/dev/Model/ComposeAttachment.js b/dev/Model/ComposeAttachment.js index e3fcf006c..c176fbf7b 100644 --- a/dev/Model/ComposeAttachment.js +++ b/dev/Model/ComposeAttachment.js @@ -1,5 +1,5 @@ import ko from 'ko'; -import { isUnd, pInt, friendlySize, mimeContentType, getFileExtension } from 'Common/Utils'; +import { pInt, friendlySize, mimeContentType, getFileExtension } from 'Common/Utils'; import { staticIconClass, staticFileType } from 'Model/Attachment'; import { AbstractModel } from 'Knoin/AbstractModel'; @@ -75,8 +75,8 @@ class ComposeAttachmentModel extends AbstractModel { let bResult = false; if (json) { this.fileName(json.Name); - this.size(isUnd(json.Size) ? 0 : pInt(json.Size)); - this.tempName(isUnd(json.TempName) ? '' : json.TempName); + this.size(undefined === json.Size ? 0 : pInt(json.Size)); + this.tempName(undefined === json.TempName ? '' : json.TempName); this.isInline = false; bResult = true; diff --git a/dev/Model/Message.js b/dev/Model/Message.js index 94bb181f2..1561fb1c2 100644 --- a/dev/Model/Message.js +++ b/dev/Model/Message.js @@ -10,8 +10,6 @@ import { DATA_IMAGE_LAZY_PLACEHOLDER_PIC } from 'Common/Consts'; import { pInt, - isArray, - isUnd, trim, previewMessage, windowResize, @@ -267,7 +265,7 @@ class MessageModel extends AbstractModel { this.unsubsribeLinks = isNonEmptyArray(json.UnsubsribeLinks) ? json.UnsubsribeLinks : []; this.subject(json.Subject); - if (isArray(json.SubjectParts)) { + if (Array.isArray(json.SubjectParts)) { this.subjectPrefix(json.SubjectParts[0]); this.subjectSuffix(json.SubjectParts[1]); } else { @@ -277,14 +275,14 @@ class MessageModel extends AbstractModel { this.dateTimeStampInUTC(pInt(json.DateTimeStampInUTC)); this.hasAttachments(!!json.HasAttachments); - this.attachmentsSpecData(isArray(json.AttachmentsSpecData) ? json.AttachmentsSpecData : []); + this.attachmentsSpecData(Array.isArray(json.AttachmentsSpecData) ? json.AttachmentsSpecData : []); this.fromEmailString(emailArrayToString(this.from, true)); this.fromClearEmailString(emailArrayToStringClear(this.from)); this.toEmailsString(emailArrayToString(this.to, true)); this.toClearEmailsString(emailArrayToStringClear(this.to)); - this.threads(isArray(json.Threads) ? json.Threads : []); + this.threads(Array.isArray(json.Threads) ? json.Threads : []); this.initFlagsByJson(json); this.computeSenderEmail(); @@ -323,9 +321,9 @@ class MessageModel extends AbstractModel { } this.hasAttachments(!!json.HasAttachments); - this.attachmentsSpecData(isArray(json.AttachmentsSpecData) ? json.AttachmentsSpecData : []); + this.attachmentsSpecData(Array.isArray(json.AttachmentsSpecData) ? json.AttachmentsSpecData : []); - this.foundedCIDs = isArray(json.FoundedCIDs) ? json.FoundedCIDs : []; + this.foundedCIDs = Array.isArray(json.FoundedCIDs) ? json.FoundedCIDs : []; this.attachments(this.initAttachmentsFromJson(json.Attachments)); this.readReceipt(json.ReadReceipt || ''); @@ -545,7 +543,7 @@ class MessageModel extends AbstractModel { * @returns {string} */ fromAsSingleEmail() { - return isArray(this.from) && this.from[0] ? this.from[0].email : ''; + return Array.isArray(this.from) && this.from[0] ? this.from[0].email : ''; } /** @@ -569,7 +567,7 @@ class MessageModel extends AbstractModel { */ replyEmails(excludeEmails, last = false) { const result = [], - unic = isUnd(excludeEmails) ? {} : excludeEmails; + unic = undefined === excludeEmails ? {} : excludeEmails; replyHelper(this.replyTo, unic, result); if (!result.length) { @@ -592,7 +590,7 @@ class MessageModel extends AbstractModel { let data = []; const toResult = [], ccResult = [], - unic = isUnd(excludeEmails) ? {} : excludeEmails; + unic = undefined === excludeEmails ? {} : excludeEmails; replyHelper(this.replyTo, unic, toResult); if (!toResult.length) { diff --git a/dev/Promises/AbstractAjax.js b/dev/Promises/AbstractAjax.js index 9d858308e..35706ad7e 100644 --- a/dev/Promises/AbstractAjax.js +++ b/dev/Promises/AbstractAjax.js @@ -1,7 +1,7 @@ import window from 'window'; import { ajax } from 'Common/Links'; -import { isUnd, isNormal, pString } from 'Common/Utils'; +import { isNormal, pString } from 'Common/Utils'; import { DEFAULT_AJAX_TIMEOUT, TOKEN_ERROR_LIMIT, AJAX_ERROR_LIMIT } from 'Common/Consts'; import { Notification } from 'Common/Enums'; import { data as GlobalsData } from 'Common/Globals'; @@ -39,7 +39,7 @@ class AbstractAjaxPromises extends AbstractBasicPromises { ajaxRequest(action, isPost, timeOut, params, additionalGetString, fTrigger) { - additionalGetString = isUnd(additionalGetString) ? '' : pString(additionalGetString); + additionalGetString = undefined === additionalGetString ? '' : pString(additionalGetString); let init = { mode: 'same-origin', @@ -155,7 +155,6 @@ class AbstractAjaxPromises extends AbstractBasicPromises { return data; }).catch(err => { -window.console.log('AbstractAjaxPromises ' + action + ' request failed:', err, Notification.getKeyByValue(err)); if (err.name == 'AbortError') { // handle abort() return Promise.reject(Notification.AjaxAbort); } @@ -164,7 +163,7 @@ window.console.log('AbstractAjaxPromises ' + action + ' request failed:', err, N } getRequest(sAction, fTrigger, sAdditionalGetString, iTimeOut) { - sAdditionalGetString = isUnd(sAdditionalGetString) ? '' : pString(sAdditionalGetString); + sAdditionalGetString = undefined === sAdditionalGetString ? '' : pString(sAdditionalGetString); sAdditionalGetString = sAction + '/' + sAdditionalGetString; return this.ajaxRequest(sAction, false, iTimeOut, null, sAdditionalGetString, fTrigger); diff --git a/dev/Promises/AbstractBasic.js b/dev/Promises/AbstractBasic.js index d70869aa9..121db2e20 100644 --- a/dev/Promises/AbstractBasic.js +++ b/dev/Promises/AbstractBasic.js @@ -1,5 +1,4 @@ import window from 'window'; -import { isArray } from 'Common/Utils'; export class AbstractBasicPromises { oPromisesStack = {}; @@ -20,7 +19,7 @@ export class AbstractBasicPromises { setTrigger(trigger, value) { if (trigger) { value = !!value; - (isArray(trigger) ? trigger : [trigger]).forEach((fTrigger) => { + (Array.isArray(trigger) ? trigger : [trigger]).forEach((fTrigger) => { if (fTrigger) { fTrigger(value); } diff --git a/dev/Promises/User/Populator.js b/dev/Promises/User/Populator.js index ca4016d06..612ac64cc 100644 --- a/dev/Promises/User/Populator.js +++ b/dev/Promises/User/Populator.js @@ -1,5 +1,5 @@ import { UNUSED_OPTION_VALUE } from 'Common/Consts'; -import { isArray, isNormal, pInt, isUnd, noop } from 'Common/Utils'; +import { isNormal, pInt } from 'Common/Utils'; import { ClientSideKeyName, ServerFolderType } from 'Common/Enums'; import * as Cache from 'Common/Cache'; @@ -21,7 +21,7 @@ class PromisesUserPopulator extends AbstractBasicPromises { * @returns {boolean} */ isFolderExpanded(sFullNameHash, expandedFolders) { - return expandedFolders && isArray(expandedFolders) && expandedFolders.includes(sFullNameHash); + return expandedFolders && Array.isArray(expandedFolders) && expandedFolders.includes(sFullNameHash); } /** @@ -84,7 +84,7 @@ class PromisesUserPopulator extends AbstractBasicPromises { oFolder.SubFolders && 'Collection/FolderCollection' === oFolder.SubFolders['@Object'] && oFolder.SubFolders['@Collection'] && - isArray(oFolder.SubFolders['@Collection']) + Array.isArray(oFolder.SubFolders['@Collection']) ) { oCacheFolder.subFolders( this.folderResponseParseRec(sNamespace, oFolder.SubFolders['@Collection'], expandedFolders) @@ -104,7 +104,7 @@ class PromisesUserPopulator extends AbstractBasicPromises { oData && 'Collection/FolderCollection' === oData['@Object'] && oData['@Collection'] && - isArray(oData['@Collection']) + Array.isArray(oData['@Collection']) ) { const expandedFolders = Local.get(ClientSideKeyName.ExpandedFolders), cnt = pInt(oData.CountRec); @@ -116,7 +116,7 @@ class PromisesUserPopulator extends AbstractBasicPromises { FolderStore.folderList( this.folderResponseParseRec( - isUnd(oData.Namespace) ? '' : oData.Namespace, + undefined === oData.Namespace ? '' : oData.Namespace, oData['@Collection'], expandedFolders ) @@ -130,9 +130,9 @@ class PromisesUserPopulator extends AbstractBasicPromises { oData && 'Collection/FolderCollection' === oData['@Object'] && oData['@Collection'] && - isArray(oData['@Collection']) + Array.isArray(oData['@Collection']) ) { - if (!isUnd(oData.Namespace)) { + if (undefined !== oData.Namespace) { FolderStore.namespace = oData.Namespace; } @@ -168,7 +168,7 @@ class PromisesUserPopulator extends AbstractBasicPromises { FolderStore.archiveFolder(this.normalizeFolder(Settings.settingsGet('ArchiveFolder'))); if (update) { - Remote.saveSystemFolders(noop, { + Remote.saveSystemFolders(()=>{}, { SentFolder: FolderStore.sentFolder(), DraftFolder: FolderStore.draftFolder(), SpamFolder: FolderStore.spamFolder(), diff --git a/dev/Remote/AbstractAjax.js b/dev/Remote/AbstractAjax.js index 35b026d4a..e0d74e198 100644 --- a/dev/Remote/AbstractAjax.js +++ b/dev/Remote/AbstractAjax.js @@ -2,7 +2,7 @@ import window from 'window'; import { TOKEN_ERROR_LIMIT, AJAX_ERROR_LIMIT, DEFAULT_AJAX_TIMEOUT } from 'Common/Consts'; import { StorageResultType, Notification } from 'Common/Enums'; -import { pInt, pString, isUnd } from 'Common/Utils'; +import { pInt, pString } from 'Common/Utils'; import { data as GlobalsData } from 'Common/Globals'; import { ajax } from 'Common/Links'; import { runHook } from 'Common/Plugins'; @@ -132,7 +132,7 @@ class AbstractAjaxRemote { ajaxRequest(fResultCallback, params, iTimeOut = 20000, sGetAdd = '', abortActions = []) { params = params || {}; const isPost = !sGetAdd, - start = new window.Date().getTime(), + start = new Date().getTime(), action = params.Action || ''; if (action && abortActions) { @@ -222,7 +222,7 @@ class AbstractAjaxRemote { return this.ajaxRequest( fCallback, oParameters, - isUnd(iTimeout) ? DEFAULT_AJAX_TIMEOUT : pInt(iTimeout), + undefined === iTimeout ? DEFAULT_AJAX_TIMEOUT : pInt(iTimeout), sGetAdd, aAbortActions ); diff --git a/dev/Remote/User/Ajax.js b/dev/Remote/User/Ajax.js index 4c072a4e1..738458b49 100644 --- a/dev/Remote/User/Ajax.js +++ b/dev/Remote/User/Ajax.js @@ -1,4 +1,4 @@ -import { pString, pInt, isArray, trim, boolToAjax } from 'Common/Utils'; +import { pString, pInt, trim } from 'Common/Utils'; import { CONTACTS_SYNC_AJAX_TIMEOUT, @@ -244,7 +244,7 @@ class RemoteUserAjax extends AbstractAjaxRemote { filtersSave(fCallback, filters, raw, isRawIsActive) { this.defaultRequest(fCallback, 'FiltersSave', { 'Raw': raw, - 'RawIsActive': boolToAjax(isRawIsActive), + 'RawIsActive': isRawIsActive ? '1' : '0', 'Filters': filters.map(item => item.toJson()) }); } @@ -449,7 +449,7 @@ class RemoteUserAjax extends AbstractAjaxRemote { let request = true; const uids = []; - if (isArray(list) && list.length) { + if (Array.isArray(list) && list.length) { request = false; list.forEach(messageListItem => { if (!getMessageFlagsFromCache(messageListItem.folderFullNameRaw, messageListItem.uid)) { @@ -473,7 +473,7 @@ class RemoteUserAjax extends AbstractAjaxRemote { if (request) { this.defaultRequest(fCallback, 'FolderInformation', { 'Folder': folder, - 'FlagsUids': isArray(uids) ? uids.join(',') : '', + 'FlagsUids': Array.isArray(uids) ? uids.join(',') : '', 'UidNext': getFolderInboxName() === folder ? getFolderUidNext(folder) : '' }); } else if (SettingsStore.useThreads()) { diff --git a/dev/Screen/AbstractSettings.js b/dev/Screen/AbstractSettings.js index 501ed3548..37a784209 100644 --- a/dev/Screen/AbstractSettings.js +++ b/dev/Screen/AbstractSettings.js @@ -1,9 +1,8 @@ -import _ from '_'; import $ from '$'; import ko from 'ko'; import { VIEW_MODELS } from 'Common/Globals'; -import { delegateRun, windowResize, log, isUnd, pString } from 'Common/Utils'; +import { delegateRun, windowResize, log, pString } from 'Common/Utils'; import { settings } from 'Common/Links'; import { setHash } from 'Knoin/Knoin'; @@ -103,24 +102,25 @@ class AbstractSettingsScreen extends AbstractScreen { } if (settingsScreen) { - _.defer(() => { + const o = this; + setTimeout(() => { // hide - if (this.oCurrentSubScreen) { - delegateRun(this.oCurrentSubScreen, 'onHide'); - this.oCurrentSubScreen.viewModelDom.hide(); + if (o.oCurrentSubScreen) { + delegateRun(o.oCurrentSubScreen, 'onHide'); + o.oCurrentSubScreen.viewModelDom.hide(); } // -- - this.oCurrentSubScreen = settingsScreen; + o.oCurrentSubScreen = settingsScreen; // show - if (this.oCurrentSubScreen) { - delegateRun(this.oCurrentSubScreen, 'onBeforeShow'); - this.oCurrentSubScreen.viewModelDom.show(); - delegateRun(this.oCurrentSubScreen, 'onShow'); - delegateRun(this.oCurrentSubScreen, 'onShowWithDelay', [], 200); + if (o.oCurrentSubScreen) { + delegateRun(o.oCurrentSubScreen, 'onBeforeShow'); + o.oCurrentSubScreen.viewModelDom.show(); + delegateRun(o.oCurrentSubScreen, 'onShow'); + delegateRun(o.oCurrentSubScreen, 'onShowWithDelay', [], 200); - this.menu().forEach(item => { + o.menu().forEach(item => { item.selected( settingsScreen && settingsScreen.__rlSettingsData && @@ -133,7 +133,7 @@ class AbstractSettingsScreen extends AbstractScreen { // -- windowResize(); - }); + }, 1); } } else { setHash(settings(), false, true); @@ -180,7 +180,7 @@ class AbstractSettingsScreen extends AbstractScreen { rules = { subname: /^(.*)$/, normalize_: (rquest, vals) => { - vals.subname = isUnd(vals.subname) ? defaultRoute : pString(vals.subname); + vals.subname = undefined === vals.subname ? defaultRoute : pString(vals.subname); return [vals.subname]; } }; diff --git a/dev/Screen/User/MailBox.js b/dev/Screen/User/MailBox.js index 7652bf4db..c6d93437e 100644 --- a/dev/Screen/User/MailBox.js +++ b/dev/Screen/User/MailBox.js @@ -1,8 +1,8 @@ -import _ from '_'; +import window from 'window'; import { Focused, Capa, ClientSideKeyName, Magics } from 'Common/Enums'; import { $html, leftPanelDisabled, leftPanelType, moveAction, bMobileDevice } from 'Common/Globals'; -import { pString, pInt, decodeURI, windowResizeCallback } from 'Common/Utils'; +import { pString, pInt, windowResizeCallback } from 'Common/Utils'; import { getFolderFromCacheList, getFolderFullNameRaw, getFolderInboxName } from 'Common/Cache'; import { i18n } from 'Common/Translator'; @@ -131,9 +131,9 @@ class MailBoxUserScreen extends AbstractScreen { */ onBuild() { if (!bMobileDevice && !Settings.appSettingsGet('mobile')) { - _.defer(() => { - getApp().initHorizontalLayoutResizer(ClientSideKeyName.MessageListSize); - }); + setTimeout(() => + getApp().initHorizontalLayoutResizer(ClientSideKeyName.MessageListSize) + , 1); } $html.on('click', '#rl-right', () => { @@ -157,7 +157,7 @@ class MailBoxUserScreen extends AbstractScreen { vals[1] = 1; } - return [decodeURI(vals[0]), vals[1], decodeURI(vals[2])]; + return [window.decodeURI(vals[0]), vals[1], window.decodeURI(vals[2])]; }, fNormD = (request, vals) => { vals[0] = pString(vals[0]); @@ -167,7 +167,7 @@ class MailBoxUserScreen extends AbstractScreen { vals[0] = inboxFolderName; } - return [decodeURI(vals[0]), 1, decodeURI(vals[1])]; + return [window.decodeURI(vals[0]), 1, window.decodeURI(vals[1])]; }; return [ diff --git a/dev/Settings/Admin/Contacts.js b/dev/Settings/Admin/Contacts.js index 029cb55f2..4098ce071 100644 --- a/dev/Settings/Admin/Contacts.js +++ b/dev/Settings/Admin/Contacts.js @@ -1,6 +1,6 @@ import ko from 'ko'; -import { settingsSaveHelperSimpleFunction, defautOptionsAfterRender, trim, boolToAjax } from 'Common/Utils'; +import { settingsSaveHelperSimpleFunction, defautOptionsAfterRender, trim } from 'Common/Utils'; import { SaveSettingsStep, StorageResultType, Magics } from 'Common/Enums'; import { i18n } from 'Common/Translator'; @@ -151,13 +151,13 @@ class ContactsAdminSettings { this.enableContacts.subscribe((value) => { Remote.saveAdminConfig(null, { - 'ContactsEnable': boolToAjax(value) + 'ContactsEnable': value ? '1' : '0' }); }); this.contactsSync.subscribe((value) => { Remote.saveAdminConfig(null, { - 'ContactsSync': boolToAjax(value) + 'ContactsSync': value ? '1' : '0' }); }); diff --git a/dev/Settings/Admin/General.js b/dev/Settings/Admin/General.js index 82401db14..55e3321dd 100644 --- a/dev/Settings/Admin/General.js +++ b/dev/Settings/Admin/General.js @@ -3,7 +3,6 @@ import ko from 'ko'; import { trim, pInt, - boolToAjax, settingsSaveHelperSimpleFunction, changeTheme, convertThemeName, @@ -116,49 +115,49 @@ class GeneralAdminSettings { this.capaAdditionalAccounts.subscribe((value) => { Remote.saveAdminConfig(null, { - 'CapaAdditionalAccounts': boolToAjax(value) + 'CapaAdditionalAccounts': value ? '1' : '0' }); }); this.capaIdentities.subscribe((value) => { Remote.saveAdminConfig(null, { - 'CapaIdentities': boolToAjax(value) + 'CapaIdentities': value ? '1' : '0' }); }); this.capaTemplates.subscribe((value) => { Remote.saveAdminConfig(null, { - 'CapaTemplates': boolToAjax(value) + 'CapaTemplates': value ? '1' : '0' }); }); this.capaAttachmentThumbnails.subscribe((value) => { Remote.saveAdminConfig(null, { - 'CapaAttachmentThumbnails': boolToAjax(value) + 'CapaAttachmentThumbnails': value ? '1' : '0' }); }); this.capaThemes.subscribe((value) => { Remote.saveAdminConfig(null, { - 'CapaThemes': boolToAjax(value) + 'CapaThemes': value ? '1' : '0' }); }); this.capaUserBackground.subscribe((value) => { Remote.saveAdminConfig(null, { - 'CapaUserBackground': boolToAjax(value) + 'CapaUserBackground': value ? '1' : '0' }); }); this.allowLanguagesOnSettings.subscribe((value) => { Remote.saveAdminConfig(null, { - 'AllowLanguagesOnSettings': boolToAjax(value) + 'AllowLanguagesOnSettings': value ? '1' : '0' }); }); this.newMoveToFolder.subscribe((value) => { Remote.saveAdminConfig(null, { - 'NewMoveToFolder': boolToAjax(value) + 'NewMoveToFolder': value ? '1' : '0' }); }); }, Magics.Time50ms); diff --git a/dev/Settings/Admin/Login.js b/dev/Settings/Admin/Login.js index dbe131e3c..547c1c32d 100644 --- a/dev/Settings/Admin/Login.js +++ b/dev/Settings/Admin/Login.js @@ -1,6 +1,6 @@ import ko from 'ko'; -import { settingsSaveHelperSimpleFunction, boolToAjax, trim } from 'Common/Utils'; +import { settingsSaveHelperSimpleFunction, trim } from 'Common/Utils'; import { settingsGet } from 'Storage/Settings'; import AppStore from 'Stores/Admin/App'; @@ -24,19 +24,19 @@ class LoginAdminSettings { this.determineUserLanguage.subscribe((value) => { Remote.saveAdminConfig(null, { - 'DetermineUserLanguage': boolToAjax(value) + 'DetermineUserLanguage': value ? '1' : '0' }); }); this.determineUserDomain.subscribe((value) => { Remote.saveAdminConfig(null, { - 'DetermineUserDomain': boolToAjax(value) + 'DetermineUserDomain': value ? '1' : '0' }); }); this.allowLanguagesOnLogin.subscribe((value) => { Remote.saveAdminConfig(null, { - 'AllowLanguagesOnLogin': boolToAjax(value) + 'AllowLanguagesOnLogin': value ? '1' : '0' }); }); diff --git a/dev/Settings/Admin/Plugins.js b/dev/Settings/Admin/Plugins.js index 0e6ee6310..c762941cd 100644 --- a/dev/Settings/Admin/Plugins.js +++ b/dev/Settings/Admin/Plugins.js @@ -2,7 +2,6 @@ import ko from 'ko'; import { StorageResultType, Notification } from 'Common/Enums'; import { getNotification } from 'Common/Translator'; -import { boolToAjax } from 'Common/Utils'; import { settingsGet } from 'Storage/Settings'; import { showScreenPopup } from 'Knoin/Knoin'; @@ -59,7 +58,7 @@ class PluginsAdminSettings { this.enabledPlugins.subscribe((value) => { Remote.saveAdminConfig(null, { - 'EnabledPlugins': boolToAjax(value) + 'EnabledPlugins': value ? '1' : '0' }); }); } diff --git a/dev/Settings/Admin/Security.js b/dev/Settings/Admin/Security.js index 9e8ec9bcf..9806c0190 100644 --- a/dev/Settings/Admin/Security.js +++ b/dev/Settings/Admin/Security.js @@ -1,6 +1,6 @@ import ko from 'ko'; -import { trim, boolToAjax } from 'Common/Utils'; +import { trim } from 'Common/Utils'; import { StorageResultType, Magics } from 'Common/Enums'; import { settingsGet } from 'Storage/Settings'; @@ -126,37 +126,37 @@ class SecurityAdminSettings { onBuild() { this.capaOpenPGP.subscribe((value) => { Remote.saveAdminConfig(null, { - 'CapaOpenPGP': boolToAjax(value) + 'CapaOpenPGP': value ? '1' : '0' }); }); this.capaTwoFactorAuth.subscribe((value) => { Remote.saveAdminConfig(null, { - 'CapaTwoFactorAuth': boolToAjax(value) + 'CapaTwoFactorAuth': value ? '1' : '0' }); }); this.capaTwoFactorAuthForce.subscribe((value) => { Remote.saveAdminConfig(null, { - 'CapaTwoFactorAuthForce': boolToAjax(value) + 'CapaTwoFactorAuthForce': value ? '1' : '0' }); }); this.useLocalProxyForExternalImages.subscribe((value) => { Remote.saveAdminConfig(null, { - 'UseLocalProxyForExternalImages': boolToAjax(value) + 'UseLocalProxyForExternalImages': value ? '1' : '0' }); }); this.verifySslCertificate.subscribe((value) => { Remote.saveAdminConfig(null, { - 'VerifySslCertificate': boolToAjax(value) + 'VerifySslCertificate': value ? '1' : '0' }); }); this.allowSelfSigned.subscribe((value) => { Remote.saveAdminConfig(null, { - 'AllowSelfSigned': boolToAjax(value) + 'AllowSelfSigned': value ? '1' : '0' }); }); } diff --git a/dev/Settings/User/Accounts.js b/dev/Settings/User/Accounts.js index febd8a3e7..f8b851a13 100644 --- a/dev/Settings/User/Accounts.js +++ b/dev/Settings/User/Accounts.js @@ -1,5 +1,4 @@ import window from 'window'; -import _ from '_'; import ko from 'ko'; import { Capa, StorageResultType } from 'Common/Enums'; @@ -69,7 +68,7 @@ class AccountsUserSettings { setHash(root(), true); routeOff(); - _.defer(() => window.location.reload()); + setTimeout(() => window.location.reload(), 1); } else { getApp().accountsAndIdentities(); } diff --git a/dev/Settings/User/Contacts.js b/dev/Settings/User/Contacts.js index c5d4cd566..372d03564 100644 --- a/dev/Settings/User/Contacts.js +++ b/dev/Settings/User/Contacts.js @@ -1,7 +1,6 @@ import ko from 'ko'; import { Magics } from 'Common/Enums'; -import { boolToAjax } from 'Common/Utils'; import AppStore from 'Stores/User/App'; import ContactStore from 'Stores/User/Contact'; @@ -32,7 +31,7 @@ class ContactsUserSettings { onBuild() { this.contactsAutosave.subscribe((value) => { Remote.saveSettings(null, { - 'ContactsAutosave': boolToAjax(value) + 'ContactsAutosave': value ? '1' : '0' }); }); diff --git a/dev/Settings/User/Filters.js b/dev/Settings/User/Filters.js index 3e8a4099a..1c1f0ed91 100644 --- a/dev/Settings/User/Filters.js +++ b/dev/Settings/User/Filters.js @@ -1,6 +1,6 @@ import ko from 'ko'; -import { windowResizeCallback, isArray, trim, delegateRunOnDestroy } from 'Common/Utils'; +import { windowResizeCallback, trim, delegateRunOnDestroy } from 'Common/Utils'; import { StorageResultType, Notification } from 'Common/Enums'; import { getNotification } from 'Common/Translator'; @@ -107,7 +107,7 @@ class FiltersUserSettings { this.filters.loading(false); this.serverError(false); - if (StorageResultType.Success === result && data && data.Result && isArray(data.Result.Filters)) { + if (StorageResultType.Success === result && data && data.Result && Array.isArray(data.Result.Filters)) { this.inited(true); this.serverError(false); @@ -121,7 +121,7 @@ class FiltersUserSettings { this.modules(data.Result.Modules ? data.Result.Modules : {}); this.filterRaw(data.Result.Raw || ''); - this.filterRaw.capa(isArray(data.Result.Capa) ? data.Result.Capa.join(' ') : ''); + this.filterRaw.capa(Array.isArray(data.Result.Capa) ? data.Result.Capa.join(' ') : ''); this.filterRaw.active(!!data.Result.RawIsActive); this.filterRaw.allow(!!data.Result.RawIsAllow); } else { diff --git a/dev/Settings/User/Folders.js b/dev/Settings/User/Folders.js index c9aa00fb4..319f87565 100644 --- a/dev/Settings/User/Folders.js +++ b/dev/Settings/User/Folders.js @@ -1,7 +1,7 @@ import ko from 'ko'; import { ClientSideKeyName, Notification, Magics } from 'Common/Enums'; -import { trim, noop } from 'Common/Utils'; +import { trim } from 'Common/Utils'; import { getNotification, i18n } from 'Common/Translator'; import { removeFolderFromCacheList } from 'Common/Cache'; @@ -130,23 +130,23 @@ class FoldersUserSettings { subscribeFolder(folder) { Local.set(ClientSideKeyName.FoldersLashHash, ''); - Remote.folderSetSubscribe(noop, folder.fullNameRaw, true); + Remote.folderSetSubscribe(()=>{}, folder.fullNameRaw, true); folder.subScribed(true); } unSubscribeFolder(folder) { Local.set(ClientSideKeyName.FoldersLashHash, ''); - Remote.folderSetSubscribe(noop, folder.fullNameRaw, false); + Remote.folderSetSubscribe(()=>{}, folder.fullNameRaw, false); folder.subScribed(false); } checkableTrueFolder(folder) { - Remote.folderSetCheckable(noop, folder.fullNameRaw, true); + Remote.folderSetCheckable(()=>{}, folder.fullNameRaw, true); folder.checkable(true); } checkableFalseFolder(folder) { - Remote.folderSetCheckable(noop, folder.fullNameRaw, false); + Remote.folderSetCheckable(()=>{}, folder.fullNameRaw, false); folder.checkable(false); } } diff --git a/dev/Settings/User/General.js b/dev/Settings/User/General.js index b3db261f1..68cdbb56a 100644 --- a/dev/Settings/User/General.js +++ b/dev/Settings/User/General.js @@ -4,7 +4,7 @@ import { MESSAGES_PER_PAGE_VALUES } from 'Common/Consts'; import { SaveSettingsStep, Magics, EditorDefaultType, Layout } from 'Common/Enums'; -import { settingsSaveHelperSimpleFunction, convertLangName, isArray, timeOutAction, boolToAjax } from 'Common/Utils'; +import { settingsSaveHelperSimpleFunction, convertLangName, timeOutAction } from 'Common/Utils'; import { i18n, trigger as translatorTrigger, reload as translatorReload } from 'Common/Translator'; @@ -55,7 +55,7 @@ class GeneralUserSettings { this.identityMain = ko.computed(() => { const list = this.identities(); - return isArray(list) ? list.find(item => item && !item.id()) : null; + return Array.isArray(list) ? list.find(item => item && !item.id()) : null; }); this.identityMainDesc = ko.computed(() => { @@ -117,16 +117,16 @@ class GeneralUserSettings { this.editorDefaultType.subscribe(Remote.saveSettingsHelper('EditorDefaultType', null, f0)); this.messagesPerPage.subscribe(Remote.saveSettingsHelper('MPP', null, f1)); - this.showImages.subscribe(Remote.saveSettingsHelper('ShowImages', boolToAjax)); + this.showImages.subscribe(Remote.saveSettingsHelper('ShowImages', v=>v?'1':'0')); - this.useCheckboxesInList.subscribe(Remote.saveSettingsHelper('UseCheckboxesInList', boolToAjax)); + this.useCheckboxesInList.subscribe(Remote.saveSettingsHelper('UseCheckboxesInList', v=>v?'1':'0')); this.enableDesktopNotification.subscribe((value) => { timeOutAction( 'SaveDesktopNotifications', () => { Remote.saveSettings(null, { - 'DesktopNotifications': boolToAjax(value) + 'DesktopNotifications': value ? '1' : '0' }); }, Magics.Time3s @@ -138,7 +138,7 @@ class GeneralUserSettings { 'SaveSoundNotification', () => { Remote.saveSettings(null, { - 'SoundNotification': boolToAjax(value) + 'SoundNotification': value ? '1' : '0' }); }, Magics.Time3s @@ -150,7 +150,7 @@ class GeneralUserSettings { 'SaveReplySameFolder', () => { Remote.saveSettings(null, { - 'ReplySameFolder': boolToAjax(value) + 'ReplySameFolder': value ? '1' : '0' }); }, Magics.Time3s @@ -160,7 +160,7 @@ class GeneralUserSettings { this.useThreads.subscribe((value) => { MessageStore.messageList([]); Remote.saveSettings(null, { - 'UseThreads': boolToAjax(value) + 'UseThreads': value ? '1' : '0' }); }); diff --git a/dev/Settings/User/OpenPgp.js b/dev/Settings/User/OpenPgp.js index 3a9b1abcd..cd6fecb0c 100644 --- a/dev/Settings/User/OpenPgp.js +++ b/dev/Settings/User/OpenPgp.js @@ -1,8 +1,7 @@ import ko from 'ko'; -import { delegateRunOnDestroy, boolToAjax } from 'Common/Utils'; +import { delegateRunOnDestroy } from 'Common/Utils'; import { Magics } from 'Common/Enums'; -import { bIsHttps } from 'Common/Globals'; import PgpStore from 'Stores/User/Pgp'; import SettingsStore from 'Stores/User/Settings'; @@ -22,8 +21,6 @@ class OpenPgpUserSettings { this.openPgpKeyForDeletion = ko.observable(null).deleteAccessHelper(); this.allowDraftAutosave = SettingsStore.allowDraftAutosave; - - this.isHttps = bIsHttps; } addOpenPgpKey() { @@ -66,7 +63,7 @@ class OpenPgpUserSettings { onBuild() { setTimeout(() => { - this.allowDraftAutosave.subscribe(Remote.saveSettingsHelper('AllowDraftAutosave', boolToAjax)); + this.allowDraftAutosave.subscribe(Remote.saveSettingsHelper('AllowDraftAutosave', v=>v?'1':'0')); }, Magics.Time50ms); } } diff --git a/dev/Storage/RainLoop.js b/dev/Storage/RainLoop.js index ea95afd85..432a94c58 100644 --- a/dev/Storage/RainLoop.js +++ b/dev/Storage/RainLoop.js @@ -51,25 +51,25 @@ const __get = (key) => { const __set = (key, value) => { if (SESS_STORAGE) { SESS_STORAGE.setItem(key, value); - } else if (WIN_STORAGE && window.JSON) { + } else if (WIN_STORAGE) { let data = WIN_STORAGE.name && '{' === WIN_STORAGE.name.toString().substr(0, 1) - ? window.JSON.parse(WIN_STORAGE.name.toString()) + ? JSON.parse(WIN_STORAGE.name.toString()) : null; data = data || {}; data[key] = value; - WIN_STORAGE.name = window.JSON.stringify(data); + WIN_STORAGE.name = JSON.stringify(data); } }; -const timestamp = () => window.Math.round(new window.Date().getTime() / 1000); +const timestamp = () => Math.round(new Date().getTime() / 1000); const setTimestamp = () => __set(TIME_KEY, timestamp()); const getTimestamp = () => { const time = __get(TIME_KEY, 0); - return time ? window.parseInt(time, 10) || 0 : 0; + return time ? parseInt(time, 10) || 0 : 0; }; /** @@ -111,4 +111,4 @@ export function checkTimestamp() { } // init section -window.setInterval(setTimestamp, 1000 * 60); // 1m +setInterval(setTimestamp, 1000 * 60); // 1m diff --git a/dev/Storage/Settings.js b/dev/Storage/Settings.js index 5eeaef011..62bb23e95 100644 --- a/dev/Storage/Settings.js +++ b/dev/Storage/Settings.js @@ -1,5 +1,5 @@ import window from 'window'; -import { isUnd, isNormal, isArray } from 'Common/Utils'; +import { isNormal } from 'Common/Utils'; let SETTINGS = window.__rlah_data() || null; SETTINGS = isNormal(SETTINGS) ? SETTINGS : {}; @@ -12,7 +12,7 @@ APP_SETTINGS = isNormal(APP_SETTINGS) ? APP_SETTINGS : {}; * @returns {*} */ export function settingsGet(name) { - return isUnd(SETTINGS[name]) ? null : SETTINGS[name]; + return undefined === SETTINGS[name] ? null : SETTINGS[name]; } /** @@ -28,7 +28,7 @@ export function settingsSet(name, value) { * @returns {*} */ export function appSettingsGet(name) { - return isUnd(APP_SETTINGS[name]) ? null : APP_SETTINGS[name]; + return undefined === APP_SETTINGS[name] ? null : APP_SETTINGS[name]; } /** @@ -37,5 +37,5 @@ export function appSettingsGet(name) { */ export function capa(name) { const values = settingsGet('Capa'); - return isArray(values) && isNormal(name) && values.includes(name); + return Array.isArray(values) && isNormal(name) && values.includes(name); } diff --git a/dev/Stores/Language.js b/dev/Stores/Language.js index ded5f537d..1430ce342 100644 --- a/dev/Stores/Language.js +++ b/dev/Stores/Language.js @@ -1,5 +1,4 @@ import ko from 'ko'; -import { isArray } from 'Common/Utils'; import * as Settings from 'Storage/Settings'; class LanguageStore { @@ -25,8 +24,8 @@ class LanguageStore { const aLanguages = Settings.appSettingsGet('languages'), aLanguagesAdmin = Settings.appSettingsGet('languagesAdmin'); - this.languages(isArray(aLanguages) ? aLanguages : []); - this.languagesAdmin(isArray(aLanguagesAdmin) ? aLanguagesAdmin : []); + this.languages(Array.isArray(aLanguages) ? aLanguages : []); + this.languagesAdmin(Array.isArray(aLanguagesAdmin) ? aLanguagesAdmin : []); this.language(Settings.settingsGet('Language')); this.languageAdmin(Settings.settingsGet('LanguageAdmin')); diff --git a/dev/Stores/Theme.js b/dev/Stores/Theme.js index 717bbcd07..3dc346e4b 100644 --- a/dev/Stores/Theme.js +++ b/dev/Stores/Theme.js @@ -1,5 +1,4 @@ import ko from 'ko'; -import { isArray } from 'Common/Utils'; import * as Settings from 'Storage/Settings'; class ThemeStore { @@ -14,7 +13,7 @@ class ThemeStore { populate() { const themes = Settings.appSettingsGet('themes'); - this.themes(isArray(themes) ? themes : []); + this.themes(Array.isArray(themes) ? themes : []); this.theme(Settings.settingsGet('Theme')); this.themeBackgroundName(Settings.settingsGet('UserBackgroundName')); this.themeBackgroundHash(Settings.settingsGet('UserBackgroundHash')); diff --git a/dev/Stores/User/Folder.js b/dev/Stores/User/Folder.js index 8ef8eced2..537b962b1 100644 --- a/dev/Stores/User/Folder.js +++ b/dev/Stores/User/Folder.js @@ -4,7 +4,7 @@ import { settingsGet } from 'Storage/Settings'; import { FolderType } from 'Common/Enums'; import { UNUSED_OPTION_VALUE } from 'Common/Consts'; -import { isArray, folderListOptionsBuilder } from 'Common/Utils'; +import { folderListOptionsBuilder } from 'Common/Utils'; import { getFolderInboxName, getFolderFromCacheList } from 'Common/Cache'; import { momentNowUnix } from 'Common/Momentor'; @@ -72,7 +72,7 @@ class FolderUserStore { trashFolder = this.trashFolder(), archiveFolder = this.archiveFolder(); - if (isArray(folders) && folders.length) { + if (Array.isArray(folders) && folders.length) { if (sentFolder && UNUSED_OPTION_VALUE !== sentFolder) { list.push(sentFolder); } diff --git a/dev/Stores/User/Message.js b/dev/Stores/User/Message.js index 35a60a04a..eb11bed6e 100644 --- a/dev/Stores/User/Message.js +++ b/dev/Stores/User/Message.js @@ -1,5 +1,4 @@ import window from 'window'; -import _ from '_'; import ko from 'ko'; import $ from '$'; @@ -8,7 +7,6 @@ import { Magics, Layout, Focused, MessageSetAction, StorageResultType, Notificat import { trim, isNormal, - isArray, pInt, pString, plainToHtml, @@ -102,7 +100,16 @@ class MessageUserStore { this.onMessageResponse = this.onMessageResponse.bind(this); - this.purgeMessageBodyCacheThrottle = _.throttle(this.purgeMessageBodyCache, Magics.Time30s); + // throttle + var t, o = this; + this.purgeMessageBodyCacheThrottle = ()=>{ + if (!t) { + t = setTimeout(()=>{ + o.purgeMessageBodyCache(); + t = 0; + }, Magics.Time30s); + } + }; } computers() { @@ -184,14 +191,17 @@ class MessageUserStore { this.messageListCompleteLoadingThrottleForAnimation(value); }); + var d; this.messageList.subscribe( - _.debounce((list) => { - list.forEach(item => { + (list)=>{ + // debounce + d && clearTimeout(d); + d = setTimeout(()=>list.forEach(item => { if (item && item.newForAnimation()) { item.newForAnimation(false); } - }); - }, Magics.Time500ms) + }), Magics.Time500ms); + } ); this.message.subscribe((message) => { @@ -249,7 +259,7 @@ class MessageUserStore { initUidNextAndNewMessages(folder, uidNext, newMessages) { if (getFolderInboxName() === folder && isNormal(uidNext) && uidNext) { - if (isArray(newMessages) && newMessages.length) { + if (Array.isArray(newMessages) && newMessages.length) { newMessages.forEach(item => { addNewMessageCache(folder, item.Uid); }); @@ -717,7 +727,7 @@ class MessageUserStore { data.Result && 'Collection/MessageCollection' === data.Result['@Object'] && data.Result['@Collection'] && - isArray(data.Result['@Collection']) + Array.isArray(data.Result['@Collection']) ) { let newCount = 0, unreadCountChange = false; diff --git a/dev/Stores/User/Pgp.js b/dev/Stores/User/Pgp.js index d7012f167..5a51dbc8a 100644 --- a/dev/Stores/User/Pgp.js +++ b/dev/Stores/User/Pgp.js @@ -1,9 +1,8 @@ import ko from 'ko'; -import _ from '_'; import $ from '$'; import { i18n } from 'Common/Translator'; -import { log, isArray, isNonEmptyArray, pString, isUnd, trim } from 'Common/Utils'; +import { log, isNonEmptyArray, pString, trim } from 'Common/Utils'; import AccountStore from 'Stores/User/Account'; @@ -56,7 +55,7 @@ class PgpUserStore { } findPrivateKeysByEncryptionKeyIds(encryptionKeyIds, recipients, returnWrapKeys) { - let result = isArray(encryptionKeyIds) + let result = Array.isArray(encryptionKeyIds) ? encryptionKeyIds.map(id => { const key = id && id.toHex ? this.findPrivateKeyByHex(id.toHex()) : null; return key ? (returnWrapKeys ? [key] : key.getNativeKeys()) : [null]; @@ -191,7 +190,7 @@ class PgpUserStore { if (publicKeys && publicKeys.length) { try { const result = message.verify(publicKeys), - valid = (_.isArray(result) ? result : []).find(item => item && item.valid && item.keyid); + valid = (Array.isArray(result) ? result : []).find(item => item && item.valid && item.keyid); if (valid && valid.keyid && valid.keyid && valid.keyid.toHex) { fCallback(this.findPublicKeyByHex(valid.keyid.toHex())); @@ -232,7 +231,7 @@ class PgpUserStore { .attr('title', title); } - if (!isUnd(text)) { + if (undefined !== text) { dom.text(trim(text)); } } diff --git a/dev/View/Popup/Activate.js b/dev/View/Popup/Activate.js index c91a2aeff..61139debe 100644 --- a/dev/View/Popup/Activate.js +++ b/dev/View/Popup/Activate.js @@ -1,7 +1,7 @@ import ko from 'ko'; import { StorageResultType, Notification } from 'Common/Enums'; -import { trim, isUnd } from 'Common/Utils'; +import { trim } from 'Common/Utils'; import { RAINLOOP_TRIAL_KEY } from 'Common/Consts'; import { i18n, getNotification } from 'Common/Translator'; @@ -89,7 +89,7 @@ class ActivatePopupView extends AbstractViewNext { onShow(isTrial) { this.domain(Settings.settingsGet('AdminDomain')); if (!this.activateProcess()) { - isTrial = isUnd(isTrial) ? false : !!isTrial; + isTrial = undefined === isTrial ? false : !!isTrial; this.key(isTrial ? RAINLOOP_TRIAL_KEY : ''); this.activateText(''); diff --git a/dev/View/Popup/Ask.js b/dev/View/Popup/Ask.js index 243598690..3c1329f25 100644 --- a/dev/View/Popup/Ask.js +++ b/dev/View/Popup/Ask.js @@ -2,7 +2,6 @@ import ko from 'ko'; import key from 'key'; import { KeyState } from 'Common/Enums'; -import { isFunc } from 'Common/Utils'; import { i18n } from 'Common/Translator'; import { popup } from 'Knoin/Knoin'; @@ -46,7 +45,7 @@ class AskPopupView extends AbstractViewNext { yesClick() { this.cancelCommand(); - if (isFunc(this.fYesAction)) { + if (typeof this.fYesAction === 'function') { this.fYesAction.call(null); } } @@ -54,7 +53,7 @@ class AskPopupView extends AbstractViewNext { noClick() { this.cancelCommand(); - if (isFunc(this.fNoAction)) { + if (typeof this.fNoAction === 'function') { this.fNoAction.call(null); } } diff --git a/dev/View/Popup/Compose.js b/dev/View/Popup/Compose.js index da0f7e86b..3cbb66397 100644 --- a/dev/View/Popup/Compose.js +++ b/dev/View/Popup/Compose.js @@ -1,5 +1,3 @@ -import window from 'window'; -import _ from '_'; import $ from '$'; import ko from 'ko'; import key from 'key'; @@ -19,18 +17,15 @@ import { import { trim, - isArray, isNormal, delegateRun, isNonEmptyArray, clearBqSwitcher, replySubjectAdd, encodeHtml, - noopFalse, inFocus, delegateRunOnDestroy, - pInt, - isUnd + pInt } from 'Common/Utils'; import { UNUSED_OPTION_VALUE } from 'Common/Consts'; @@ -291,8 +286,8 @@ class ComposePopupView extends AbstractViewNext { } }); - this.attachmentsInProcess.subscribe((value) => { - if (this.attachmentsInProcessError() && isArray(value) && value.length) { + this.attachmentsInProcess.subscribe(value => { + if (this.attachmentsInProcessError() && isNonEmptyArray(value)) { this.attachmentsInProcessError(false); } }); @@ -333,7 +328,12 @@ class ComposePopupView extends AbstractViewNext { this.bDisabeCloseOnEsc = true; this.sDefaultKeyScope = KeyState.Compose; - this.tryToClosePopup = _.debounce(this.tryToClosePopup.bind(this), Magics.Time200ms); + // debounce + var d, fn = this.tryToClosePopup.bind(this); + this.tryToClosePopup = ()=>{ + d && clearTimeout(d); + d = setTimeout(fn, Magics.Time200ms); + }; this.emailsSource = this.emailsSource.bind(this); this.autosaveFunction = this.autosaveFunction.bind(this); @@ -367,7 +367,7 @@ class ComposePopupView extends AbstractViewNext { if (!this.emptyToError() && !this.attachmentsInErrorError() && !this.attachmentsInProcessError()) { if (SettingsStore.replySameFolder()) { if ( - isArray(this.aDraftInfo) && + Array.isArray(this.aDraftInfo) && 3 === this.aDraftInfo.length && isNormal(this.aDraftInfo[2]) && this.aDraftInfo[2].length @@ -386,7 +386,7 @@ class ComposePopupView extends AbstractViewNext { this.sendError(false); this.sending(true); - if (isArray(this.aDraftInfo) && 3 === this.aDraftInfo.length) { + if (Array.isArray(this.aDraftInfo) && 3 === this.aDraftInfo.length) { const flagsCache = getMessageFlagsFromCache(this.aDraftInfo[2], this.aDraftInfo[1]); if (flagsCache) { if ('forward' === this.aDraftInfo[0]) { @@ -531,12 +531,12 @@ class ComposePopupView extends AbstractViewNext { } autosaveStart() { - window.clearTimeout(this.iTimer); - this.iTimer = window.setTimeout(this.autosaveFunction, Magics.Time1m); + clearTimeout(this.iTimer); + this.iTimer = setTimeout(this.autosaveFunction, Magics.Time1m); } autosaveStop() { - window.clearTimeout(this.iTimer); + clearTimeout(this.iTimer); } emailsSource(oData, fResponse) { @@ -672,7 +672,7 @@ class ComposePopupView extends AbstractViewNext { this.draftFolder(oData.Result.NewFolder); this.draftUid(oData.Result.NewUid); - this.savedTime(window.Math.round(new window.Date().getTime() / 1000)); + this.savedTime(Math.round(new Date().getTime() / 1000)); if (this.bFromDraft) { setFolderHash(this.draftFolder(), ''); @@ -907,9 +907,9 @@ class ComposePopupView extends AbstractViewNext { oMessageOrArray = oMessageOrArray || null; if (oMessageOrArray && isNormal(oMessageOrArray)) { message = - isArray(oMessageOrArray) && 1 === oMessageOrArray.length + Array.isArray(oMessageOrArray) && 1 === oMessageOrArray.length ? oMessageOrArray[0] - : !isArray(oMessageOrArray) + : !Array.isArray(oMessageOrArray) ? oMessageOrArray : null; } @@ -1207,7 +1207,7 @@ class ComposePopupView extends AbstractViewNext { onBuild() { this.initUploader(); - key('ctrl+q, command+q, ctrl+w, command+w', KeyState.Compose, noopFalse); + key('ctrl+q, command+q, ctrl+w, command+w', KeyState.Compose, ()=>false); key('`', KeyState.Compose, () => { if (this.oEditor && !this.oEditor.hasFocus() && !inFocus()) { @@ -1250,9 +1250,14 @@ class ComposePopupView extends AbstractViewNext { }); Events.sub('window.resize.real', this.resizerTrigger); - Events.sub('window.resize.real', _.debounce(this.resizerTrigger, Magics.Time50ms)); + var d, o = this; + Events.sub('window.resize.real', ()=>{ + // debounce + d && clearTimeout(d); + d = setTimeout(o.resizerTrigger, Magics.Time50ms); + }); - window.setInterval(() => { + setInterval(() => { if (this.modalVisibility() && this.oEditor) { this.oEditor.resize(); } @@ -1322,13 +1327,13 @@ class ComposePopupView extends AbstractViewNext { } if (item) { - item.progress(window.Math.floor((loaded / total) * 100)); + item.progress(Math.floor((loaded / total) * 100)); } }) .on('onSelect', (sId, oData) => { this.dragAndDropOver(false); - const fileName = isUnd(oData.FileName) ? '' : oData.FileName.toString(), + const fileName = undefined === oData.FileName ? '' : oData.FileName.toString(), size = isNormal(oData.Size) ? pInt(oData.Size) : null, attachment = new ComposeAttachmentModel(sId, fileName, size); @@ -1394,7 +1399,7 @@ class ComposePopupView extends AbstractViewNext { attachment.initByUploadJson(attachmentJson); } - if (isUnd(uploadCache[id])) { + if (undefined === uploadCache[id]) { delete uploadCache[id]; } } diff --git a/dev/View/Popup/ComposeOpenPgp.js b/dev/View/Popup/ComposeOpenPgp.js index 56b973d6c..78998bdce 100644 --- a/dev/View/Popup/ComposeOpenPgp.js +++ b/dev/View/Popup/ComposeOpenPgp.js @@ -2,7 +2,7 @@ import $ from '$'; import ko from 'ko'; import key from 'key'; -import { pString, log, isUnd, trim, defautOptionsAfterRender } from 'Common/Utils'; +import { pString, log, trim, defautOptionsAfterRender } from 'Common/Utils'; import { Magics, KeyState } from 'Common/Enums'; import { i18n } from 'Common/Translator'; @@ -102,7 +102,7 @@ class ComposeOpenPgpPopupView extends AbstractViewNext { this.addOptionClass = (domOption, item) => { this.defautOptionsAfterRender(domOption, item); - if (item && !isUnd(item.class) && domOption) { + if (item && undefined !== item.class && domOption) { $(domOption).addClass(item.class); } }; diff --git a/dev/View/Popup/Contacts.js b/dev/View/Popup/Contacts.js index a0f8036e7..6dbe8dde8 100644 --- a/dev/View/Popup/Contacts.js +++ b/dev/View/Popup/Contacts.js @@ -22,8 +22,7 @@ import { windowResizeCallback, isNonEmptyArray, fakeMd5, - pInt, - isUnd + pInt } from 'Common/Utils'; import { CONTACTS_PER_PAGE } from 'Common/Consts'; @@ -649,8 +648,8 @@ class ContactsPopupView extends AbstractViewNext { } onShow(bBackToCompose, sLastComposeFocusedField) { - this.bBackToCompose = isUnd(bBackToCompose) ? false : !!bBackToCompose; - this.sLastComposeFocusedField = isUnd(sLastComposeFocusedField) ? '' : sLastComposeFocusedField; + this.bBackToCompose = undefined === bBackToCompose ? false : !!bBackToCompose; + this.sLastComposeFocusedField = undefined === sLastComposeFocusedField ? '' : sLastComposeFocusedField; routeOff(); this.reloadContactList(true); diff --git a/dev/View/Popup/FolderSystem.js b/dev/View/Popup/FolderSystem.js index a59b96f3d..bf399a107 100644 --- a/dev/View/Popup/FolderSystem.js +++ b/dev/View/Popup/FolderSystem.js @@ -1,9 +1,8 @@ -import _ from '_'; import ko from 'ko'; import { SetSystemFoldersNotification, Magics } from 'Common/Enums'; import { UNUSED_OPTION_VALUE } from 'Common/Consts'; -import { folderListOptionsBuilder, noop, defautOptionsAfterRender } from 'Common/Utils'; +import { folderListOptionsBuilder, defautOptionsAfterRender } from 'Common/Utils'; import { initOnStartOrLangChange, i18n } from 'Common/Translator'; import FolderStore from 'Stores/User/Folder'; @@ -56,6 +55,7 @@ class FolderSystemPopupView extends AbstractViewNext { this.trashFolder = FolderStore.trashFolder; this.archiveFolder = FolderStore.archiveFolder; + var d; const fSetSystemFolders = () => { Settings.settingsSet('SentFolder', FolderStore.sentFolder()); Settings.settingsSet('DraftFolder', FolderStore.draftFolder()); @@ -63,17 +63,21 @@ class FolderSystemPopupView extends AbstractViewNext { Settings.settingsSet('TrashFolder', FolderStore.trashFolder()); Settings.settingsSet('ArchiveFolder', FolderStore.archiveFolder()); }, - fSaveSystemFolders = _.debounce(() => { - fSetSystemFolders(); - Remote.saveSystemFolders(noop, { - SentFolder: FolderStore.sentFolder(), - DraftFolder: FolderStore.draftFolder(), - SpamFolder: FolderStore.spamFolder(), - TrashFolder: FolderStore.trashFolder(), - ArchiveFolder: FolderStore.archiveFolder(), - NullFolder: 'NullFolder' - }); - }, Magics.Time1s), + fSaveSystemFolders = ()=>{ + // debounce + d && clearTimeout(d); + d = setTimeout(()=>{ + fSetSystemFolders(); + Remote.saveSystemFolders(()=>{}, { + SentFolder: FolderStore.sentFolder(), + DraftFolder: FolderStore.draftFolder(), + SpamFolder: FolderStore.spamFolder(), + TrashFolder: FolderStore.trashFolder(), + ArchiveFolder: FolderStore.archiveFolder(), + NullFolder: 'NullFolder' + }); + }, Magics.Time1s); + }, fCallback = () => { fSetSystemFolders(); fSaveSystemFolders(); diff --git a/dev/View/Popup/KeyboardShortcutsHelp.js b/dev/View/Popup/KeyboardShortcutsHelp.js index 55d67204c..5528c81f2 100644 --- a/dev/View/Popup/KeyboardShortcutsHelp.js +++ b/dev/View/Popup/KeyboardShortcutsHelp.js @@ -1,4 +1,3 @@ -import _ from '_'; import key from 'key'; import { KeyState, Magics } from 'Common/Enums'; @@ -17,32 +16,39 @@ class KeyboardShortcutsHelpPopupView extends AbstractViewNext { } onBuild(dom) { + var t; key( 'tab, shift+tab, left, right', KeyState.PopupKeyboardShortcutsHelp, - _.throttle((event, handler) => { - if (event && handler) { - const $tabs = dom.find('.nav.nav-tabs > li'), - isNext = handler && ('tab' === handler.shortcut || 'right' === handler.shortcut); + (event, handler)=>{ + // throttle + if (!t) { + t = setTimeout(()=>{ + t = 0; + if (event && handler) { + const $tabs = dom.find('.nav.nav-tabs > li'), + isNext = handler && ('tab' === handler.shortcut || 'right' === handler.shortcut); - let index = $tabs.index($tabs.filter('.active')); - if (!isNext && 0 < index) { - index -= 1; - } else if (isNext && index < $tabs.length - 1) { - index += 1; - } else { - index = isNext ? 0 : $tabs.length - 1; - } + let index = $tabs.index($tabs.filter('.active')); + if (!isNext && 0 < index) { + index -= 1; + } else if (isNext && index < $tabs.length - 1) { + index += 1; + } else { + index = isNext ? 0 : $tabs.length - 1; + } - $tabs - .eq(index) - .find('a[data-toggle="tab"]') - .tab('show'); - return false; + $tabs + .eq(index) + .find('a[data-toggle="tab"]') + .tab('show'); + return false; + } + + return true; + }, Magics.Time100ms); } - - return true; - }, Magics.Time100ms) + } ); } } diff --git a/dev/View/Popup/Plugin.js b/dev/View/Popup/Plugin.js index 48847c6d3..6312aad18 100644 --- a/dev/View/Popup/Plugin.js +++ b/dev/View/Popup/Plugin.js @@ -1,4 +1,3 @@ -import _ from '_'; import ko from 'ko'; import key from 'key'; @@ -43,7 +42,12 @@ class PluginPopupView extends AbstractViewNext { this.bDisabeCloseOnEsc = true; this.sDefaultKeyScope = KeyState.All; - this.tryToClosePopup = _.debounce(this.tryToClosePopup.bind(this), Magics.Time200ms); + var d, fn = this.tryToClosePopup.bind(this); + this.tryToClosePopup = ()=>{ + // debounce + d && clearTimeout(d); + d = setTimeout(fn, Magics.Time200ms); + }; } @command((self) => self.hasConfiguration()) diff --git a/dev/View/User/AbstractSystemDropDown.js b/dev/View/User/AbstractSystemDropDown.js index 3b91ae0e2..e6b0b35a4 100644 --- a/dev/View/User/AbstractSystemDropDown.js +++ b/dev/View/User/AbstractSystemDropDown.js @@ -6,7 +6,7 @@ import AccountStore from 'Stores/User/Account'; import MessageStore from 'Stores/User/Message'; import { Capa, Magics, KeyState } from 'Common/Enums'; -import { trim, isUnd } from 'Common/Utils'; +import { trim } from 'Common/Utils'; import { settings } from 'Common/Links'; import * as Events from 'Common/Events'; @@ -51,7 +51,7 @@ class AbstractSystemDropDownUserView extends AbstractViewNext { } accountClick(account, event) { - if (account && event && !isUnd(event.which) && 1 === event.which) { + if (account && event && undefined !== event.which && 1 === event.which) { AccountStore.accounts.loading(true); setTimeout(() => AccountStore.accounts.loading(false), Magics.Time1s); } diff --git a/dev/View/User/MailBox/FolderList.js b/dev/View/User/MailBox/FolderList.js index f6f6c701f..a086de3ca 100644 --- a/dev/View/User/MailBox/FolderList.js +++ b/dev/View/User/MailBox/FolderList.js @@ -3,7 +3,7 @@ import $ from '$'; import ko from 'ko'; import key from 'key'; -import { trim, isNormal, isArray, windowResize } from 'Common/Utils'; +import { trim, isNormal, windowResize } from 'Common/Utils'; import { Capa, Focused, Layout, KeyState, EventKeyCode, Magics } from 'Common/Enums'; import { $htmlCL, leftPanelDisabled, moveAction } from 'Common/Globals'; import { mailBox, settings } from 'Common/Links'; @@ -245,7 +245,7 @@ class FolderListMailBoxUserView extends AbstractViewNext { copy = $htmlCL.contains('rl-ctrl-key-pressed'), uids = ui.helper.data('rl-uids'); - if (fromFolderFullNameRaw && isNormal(fromFolderFullNameRaw) && isArray(uids)) { + if (fromFolderFullNameRaw && isNormal(fromFolderFullNameRaw) && Array.isArray(uids)) { getApp().moveMessagesToFolder(fromFolderFullNameRaw, uids, toFolder.fullNameRaw, copy); } } diff --git a/dev/View/User/MailBox/MessageList.js b/dev/View/User/MailBox/MessageList.js index 88c59b299..c6b3cb19a 100644 --- a/dev/View/User/MailBox/MessageList.js +++ b/dev/View/User/MailBox/MessageList.js @@ -1,5 +1,4 @@ import window from 'window'; -import _ from '_'; import $ from '$'; import ko from 'ko'; import key from 'key'; @@ -22,7 +21,7 @@ import { UNUSED_OPTION_VALUE } from 'Common/Consts'; import { bMobileDevice, popupVisibility, leftPanelDisabled, moveAction } from 'Common/Globals'; -import { noop, noopFalse, computedPagenatorHelper, draggablePlace, friendlySize, isUnd } from 'Common/Utils'; +import { computedPagenatorHelper, draggablePlace, friendlySize } from 'Common/Utils'; import { mailBox, append } from 'Common/Links'; import { Selector } from 'Common/Selector'; @@ -401,7 +400,7 @@ class MessageListMailBoxUserView extends AbstractViewNext { } window.clearTimeout(this.iGoToUpUpOrDownDownTimeout); - this.iGoToUpUpOrDownDownTimeout = window.setTimeout(() => { + this.iGoToUpUpOrDownDownTimeout = setTimeout(() => { let prev = null, next = null, temp = null, @@ -516,7 +515,7 @@ class MessageListMailBoxUserView extends AbstractViewNext { el.data('rl-folder', FolderStore.currentFolderFullNameRaw()); updateUidsInfo(); - _.defer(updateUidsInfo); + setTimeout(updateUidsInfo,1); return el; } @@ -569,7 +568,7 @@ class MessageListMailBoxUserView extends AbstractViewNext { clearMessageFlagsFromCacheByFolder(sFolderFullNameRaw); } - Remote.messageSetSeenToAll(noop, sFolderFullNameRaw, true, sThreadUid ? uids : null); + Remote.messageSetSeenToAll(()=>{}, sFolderFullNameRaw, true, sThreadUid ? uids : null); break; case MessageSetAction.UnsetSeen: folder = getFolderFromCacheList(sFolderFullNameRaw); @@ -595,7 +594,7 @@ class MessageListMailBoxUserView extends AbstractViewNext { clearMessageFlagsFromCacheByFolder(sFolderFullNameRaw); } - Remote.messageSetSeenToAll(noop, sFolderFullNameRaw, false, sThreadUid ? uids : null); + Remote.messageSetSeenToAll(()=>{}, sFolderFullNameRaw, false, sThreadUid ? uids : null); break; // no default } @@ -668,7 +667,7 @@ class MessageListMailBoxUserView extends AbstractViewNext { flagMessagesFast(bFlag) { const checked = this.messageListCheckedOrSelected(); if (checked.length) { - if (isUnd(bFlag)) { + if (undefined === bFlag) { const flagged = checked.filter(message => message.flagged()); this.setAction( checked[0].folderFullNameRaw, @@ -688,7 +687,7 @@ class MessageListMailBoxUserView extends AbstractViewNext { seenMessagesFast(seen) { const checked = this.messageListCheckedOrSelected(); if (checked.length) { - if (isUnd(seen)) { + if (undefined === seen) { const unseen = checked.filter(message => message.unseen()); this.setAction( checked[0].folderFullNameRaw, @@ -932,8 +931,8 @@ class MessageListMailBoxUserView extends AbstractViewNext { return false; }); - key('ctrl+left, command+left', KeyState.MessageView, noopFalse); - key('ctrl+right, command+right', KeyState.MessageView, noopFalse); + key('ctrl+left, command+left', KeyState.MessageView, ()=>false); + key('ctrl+right, command+right', KeyState.MessageView, ()=>false); } prefetchNextTick() { diff --git a/dev/View/User/MailBox/MessageView.js b/dev/View/User/MailBox/MessageView.js index 25dc4563f..c13bfb80c 100644 --- a/dev/View/User/MailBox/MessageView.js +++ b/dev/View/User/MailBox/MessageView.js @@ -1,4 +1,3 @@ -import _ from '_'; import $ from '$'; import ko from 'ko'; import key from 'key'; @@ -22,7 +21,6 @@ import { $htmlCL, leftPanelDisabled, keyScopeReal, useKeyboardShortcuts, moveAct import { isNonEmptyArray, trim, - noop, windowResize, windowResizeCallback, inFocus, @@ -542,13 +540,20 @@ class MessageViewMailBoxUserView extends AbstractViewNext { this.showFullInfo.subscribe(fCheckHeaderHeight); this.message.subscribe(fCheckHeaderHeight); + var t; Events.sub( 'window.resize', - _.throttle(() => { - setTimeout(fCheckHeaderHeight, 1); - setTimeout(fCheckHeaderHeight, Magics.Time200ms); - setTimeout(fCheckHeaderHeight, Magics.Time500ms); - }, Magics.Time50ms) + ()=>{ + // throttle + if (!t) { + t = setTimeout(()=>{ + setTimeout(fCheckHeaderHeight, 1); + setTimeout(fCheckHeaderHeight, Magics.Time200ms); + setTimeout(fCheckHeaderHeight, Magics.Time500ms); + t = 0; + }, Magics.Time50ms); + } + } ); this.showFullInfo.subscribe((value) => { @@ -932,7 +937,7 @@ class MessageViewMailBoxUserView extends AbstractViewNext { readReceipt(oMessage) { if (oMessage && oMessage.readReceipt()) { Remote.sendReadReceiptMessage( - noop, + ()=>{}, oMessage.folderFullNameRaw, oMessage.uid, oMessage.readReceipt(), diff --git a/dev/bootstrap.js b/dev/bootstrap.js index 90204016c..4002a7046 100644 --- a/dev/bootstrap.js +++ b/dev/bootstrap.js @@ -1,5 +1,5 @@ import window from 'window'; -import { killCtrlACtrlS, detectDropdownVisibility, createCommandLegacy, domReady } from 'Common/Utils'; +import { detectDropdownVisibility, createCommandLegacy, domReady } from 'Common/Utils'; import { $html, $htmlCL, data as GlobalsData, bMobileDevice } from 'Common/Globals'; import * as Enums from 'Common/Enums'; import * as Plugins from 'Common/Plugins'; @@ -9,7 +9,32 @@ import { EmailModel } from 'Model/Email'; export default (App) => { GlobalsData.__APP__ = App; - window.addEventListener('keydown', killCtrlACtrlS); + window.addEventListener('keydown', event => { + event = event || window.event; + if (event && event.ctrlKey && !event.shiftKey && !event.altKey) { + const key = event.keyCode || event.which; + if (key === Enums.EventKeyCode.S) { + event.preventDefault(); + return; + } else if (key === Enums.EventKeyCode.A) { + const sender = event.target || event.srcElement; + if ( + sender && + ('true' === '' + sender.contentEditable || (sender.tagName && sender.tagName.match(/INPUT|TEXTAREA/i))) + ) { + return; + } + + if (window.getSelection) { + window.getSelection().removeAllRanges(); + } else if (window.document.selection && window.document.selection.clear) { + window.document.selection.clear(); + } + + event.preventDefault(); + } + } + }); window.addEventListener('unload', () => { GlobalsData.bUnload = true; }); diff --git a/tasks/config.js b/tasks/config.js index ddca9f9b2..7c6bdd15f 100644 --- a/tasks/config.js +++ b/tasks/config.js @@ -83,7 +83,6 @@ config.paths.js = { 'vendors/keymaster/keymaster.js', // custom (modified) 'vendors/qr.js/qr.min.js', // fixed (license) 'vendors/bootstrap/js/bootstrap.min.js', // fixed - 'vendors/underscore/underscore-min.custom.js', 'node_modules/moment/min/moment.min.js', 'node_modules/knockout/build/output/knockout-latest.js', 'node_modules/knockout-sortable/build/knockout-sortable.min.js ', diff --git a/vendors/underscore/underscore-min.custom.js b/vendors/underscore/underscore-min.custom.js deleted file mode 100644 index 6a54ee2d5..000000000 --- a/vendors/underscore/underscore-min.custom.js +++ /dev/null @@ -1,6 +0,0 @@ -// Underscore.js 1.9.2 -// https://underscorejs.org -// (c) 2009-2018 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors -// Underscore may be freely distributed under the MIT license. - -(()=>{var e=function(){};("object"==typeof self&&self.self===self&&self||{})._=e;e.defer=(()=>{var e=(e,t,...l)=>setTimeout(()=>e.apply(null,l),t),t=function(...l){for(var n=1,r=[l[0],1];n{var c=Date.now();o||!1!==l.leading||(o=c);var p=t-(c-o);return r=this,p<=0||p>t?(n&&(clearTimeout(n),n=null),o=c,a=e.apply(r,u),n||(r=u=null)):n||!1===l.trailing||(n=setTimeout(i,p)),a};return c.cancel=(()=>{clearTimeout(n),o=0,n=r=u=null}),c},e.debounce=function(e,t,l){var n,r,u=(t,l)=>{n=null,l&&(r=e.apply(t,l))},a=function(...a){if(n&&clearTimeout(n),l){var o=!n;n=setTimeout(u,t),o&&(r=e.apply(this,a))}else{var i=this;n=setTimeout(()=>u.apply(null,[i,a]),t)}return r};return a.cancel=(()=>{clearTimeout(n),n=null}),a}})(); diff --git a/vendors/underscore/underscore.custom.js b/vendors/underscore/underscore.custom.js deleted file mode 100644 index 7faaf9bba..000000000 --- a/vendors/underscore/underscore.custom.js +++ /dev/null @@ -1,124 +0,0 @@ -// Underscore.js 1.9.2 -// https://underscorejs.org -// (c) 2009-2018 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors -// Underscore may be freely distributed under the MIT license. -/* -_.debounce -_.defer -_.throttle -*/ - -(() => { - - // Baseline setup - // -------------- - - // Create a safe reference to the Underscore object for use below. - var _ = function() { }; - - // Establish the root object, `window` (`self`) in the browser. - // We use `self`instead of `window` for `WebWorker` support. - (typeof self == 'object' && self.self === self && self || {})._ = _; - - // Function (ahem) Functions - // ------------------ - - // Determines whether to execute a function as a constructor - // or a normal function with the provided arguments. - var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) { - if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args); - var fp = sourceFunc.prototype, - self = (typeof fp !== 'object') ? {} : Object.create(fp), - result = sourceFunc.apply(self, args); - return (typeof result === 'object') ? result : self; - }; - - // Defers a function, scheduling it to run after the current call stack has - // cleared. - _.defer = (() => { - var func = (func, wait, ...args) => setTimeout(() => func.apply(null, args), wait), - bound = function(...params) { - var pos = 1, - args = [params[0], 1]; - while (pos < params.length) args.push(params[pos++]); - return executeBound(func, bound, this, this, args); - }; - return bound; - })(); - - // Returns a function, that, when invoked, will only be triggered at most once - // during a given window of time. Normally, the throttled function will run - // as much as it can, without ever going more than once per `wait` duration; - // but if you'd like to disable the execution on the leading edge, pass - // `{leading: false}`. To disable execution on the trailing edge, ditto. - _.throttle = function(func, wait, options) { - if (!options) options = {}; - var timeout, context, args, result, - previous = 0, - later = function() { - previous = options.leading === false ? 0 : Date.now(); - timeout = null; - result = func.apply(context, args); - if (!timeout) context = args = null; - }, - throttle = (...args) => { - var now = Date.now(); - if (!previous && options.leading === false) previous = now; - var remaining = wait - (now - previous); - context = this; - if (remaining <= 0 || remaining > wait) { - if (timeout) { - clearTimeout(timeout); - timeout = null; - } - previous = now; - result = func.apply(context, args); - if (!timeout) context = args = null; - } else if (!timeout && options.trailing !== false) { - timeout = setTimeout(later, remaining); - } - return result; - }; - - throttle.cancel = () => { - clearTimeout(timeout); - previous = 0; - timeout = context = args = null; - }; - - return throttle; - }; - - // Returns a function, that, as long as it continues to be invoked, will not - // be triggered. The function will be called after it stops being called for - // N milliseconds. If `immediate` is passed, trigger the function on the - // leading edge, instead of the trailing. - _.debounce = function(func, wait, immediate) { - var timeout, result, - later = (context, args) => { - timeout = null; - if (args) result = func.apply(context, args); - }, - debounce = function(...args) { - if (timeout) clearTimeout(timeout); - if (immediate) { - var callNow = !timeout; - timeout = setTimeout(later, wait); - if (callNow) result = func.apply(this, args); - } else { - var obj = this; - timeout = setTimeout(() => later.apply(null, [obj, args]), wait); - } - - return result; - }; - - debounce.cancel = () => { - clearTimeout(timeout); - timeout = null; - }; - - return debounce; - }; - -})();