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
This commit is contained in:
djmaze 2020-07-29 21:49:41 +02:00
parent fa39c7ecba
commit ea48f5060b
72 changed files with 551 additions and 775 deletions

View file

@ -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

View file

@ -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);

View file

@ -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]);

View file

@ -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();

View file

@ -88,7 +88,6 @@ window.__initAppData = data => {
const appData = window.__rlah_data(), p = progressJs;
if (
jassl &&
p &&
appData &&
appData.TemplatesLink &&

View file

@ -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;
}

View file

@ -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;

View file

@ -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;

View file

@ -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 || []);

View file

@ -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: [],

View file

@ -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();
}

View file

@ -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);

View file

@ -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) + '/';
}
/**

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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);
}
/**

View file

@ -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
);
});
});

View file

@ -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,/`/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}

View file

@ -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');
}
}

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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 })));

View file

@ -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;
}
}

18
dev/External/ko.js vendored
View file

@ -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);

View file

@ -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);
}

View file

@ -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);
}
}

View file

@ -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) => {

View file

@ -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 {

View file

@ -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

View file

@ -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;

View file

@ -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) {

View file

@ -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);

View file

@ -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);
}

View file

@ -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(),

View file

@ -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
);

View file

@ -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()) {

View file

@ -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];
}
};

View file

@ -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 [

View file

@ -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'
});
});

View file

@ -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);

View file

@ -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'
});
});

View file

@ -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'
});
});
}

View file

@ -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'
});
});
}

View file

@ -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();
}

View file

@ -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'
});
});

View file

@ -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 {

View file

@ -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);
}
}

View file

@ -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'
});
});

View file

@ -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);
}
}

View file

@ -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

View file

@ -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);
}

View file

@ -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'));

View file

@ -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'));

View file

@ -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);
}

View file

@ -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;

View file

@ -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));
}
}

View file

@ -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('');

View file

@ -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);
}
}

View file

@ -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];
}
}

View file

@ -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);
}
};

View file

@ -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);

View file

@ -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();

View file

@ -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)
}
);
}
}

View file

@ -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())

View file

@ -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);
}

View file

@ -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);
}
}

View file

@ -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() {

View file

@ -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(),

29
dev/bootstrap.js vendored
View file

@ -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;
});

View file

@ -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 ',

View file

@ -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<l.length;)r.push(l[n++]);return function(e,t,l,n,r){if(!(n instanceof t))return e.apply(l,r);var u=e.prototype,a="object"!=typeof u?{}:Object.create(u),o=e.apply(a,r);return"object"==typeof o?o:a}(e,t,this,this,r)};return t})(),e.throttle=function(e,t,l){l||(l={});var n,r,u,a,o=0,i=function(){o=!1===l.leading?0:Date.now(),n=null,a=e.apply(r,u),n||(r=u=null)},c=(...u)=>{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}})();

View file

@ -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;
};
})();