mirror of
https://github.com/the-djmaze/snappymail.git
synced 2024-12-27 09:36:09 +08:00
Replace timeOutAction() with debounce
Replace delegateRun() Revert my throttle/debounce setTimeout() to Function.prototype[throttle/debounce]
This commit is contained in:
parent
f6a55898c7
commit
97a73c6639
28 changed files with 225 additions and 372 deletions
24
README.md
24
README.md
|
@ -59,7 +59,7 @@ This fork uses downsized/simplified versions of scripts and has no support for I
|
|||
|
||||
The result is faster and smaller download code (good for mobile networks).
|
||||
|
||||
Things might work in Edge 16-18, Firefox 50-62 and Chrome 54-68 due to one polyfill for array.flat().
|
||||
Things might work in Edge 18, Firefox 50-62 and Chrome 54-68 due to one polyfill for array.flat().
|
||||
|
||||
* Replaced jQuery with jQuery.slim
|
||||
* Replaced ProgressJS with simple native dropin
|
||||
|
@ -79,23 +79,23 @@ Things might work in Edge 16-18, Firefox 50-62 and Chrome 54-68 due to one polyf
|
|||
|
||||
|js/* |1.14.0 |native |
|
||||
|----------- |--------: |--------: |
|
||||
|admin.js |2.130.942 |1.089.940 |
|
||||
|app.js |4.184.455 |2.774.461 |
|
||||
|boot.js | 671.522 | 44.029 |
|
||||
|libs.js | 647.614 | 316.107 |
|
||||
|admin.js |2.130.942 |1.082.985 |
|
||||
|app.js |4.184.455 |2.751.154 |
|
||||
|boot.js | 671.522 | 43.995 |
|
||||
|libs.js | 647.614 | 316.876 |
|
||||
|polyfills.js | 325.834 | 0 |
|
||||
|TOTAL |7.960.367 |4.224.537 |
|
||||
|TOTAL |7.960.367 |4.195.010 |
|
||||
|
||||
|js/min/* |1.14.0 |native |gzip 1.14 |gzip |
|
||||
|--------------- |--------: |--------: |--------: |--------: |
|
||||
|admin.min.js | 252.147 | 148.234 | 73.657 | 42.376 |
|
||||
|app.min.js | 511.202 | 371.731 |140.462 | 97.432 |
|
||||
|boot.min.js | 66.007 | 5.589 | 22.567 | 2.332 |
|
||||
|libs.min.js | 572.545 | 300.211 |176.720 | 92.699 |
|
||||
|admin.min.js | 252.147 | 147.526 | 73.657 | 42.213 |
|
||||
|app.min.js | 511.202 | 369.396 |140.462 | 97.130 |
|
||||
|boot.min.js | 66.007 | 5.579 | 22.567 | 2.328 |
|
||||
|libs.min.js | 572.545 | 300.520 |176.720 | 92.825 |
|
||||
|polyfills.min.js | 32.452 | 0 | 11.312 | 0 |
|
||||
|TOTAL |1.434.353 | 825.765 |424.718 |234.839 |
|
||||
|TOTAL |1.434.353 | 823.015 |424.718 |234.496 |
|
||||
|
||||
608.588 bytes (189.879 gzip) is not much, but it feels faster.
|
||||
611.338 bytes (190.222 gzip) is not much, but it feels faster.
|
||||
|
||||
|
||||
|css/* |1.14.0 |native |
|
||||
|
|
|
@ -31,25 +31,18 @@ class AbstractApp extends AbstractBoot {
|
|||
this.isLocalAutocomplete = true;
|
||||
this.lastErrorTime = 0;
|
||||
|
||||
var t;
|
||||
addEventListener(
|
||||
'resize',
|
||||
()=>{
|
||||
// throttle
|
||||
if (!t) {
|
||||
t = setTimeout(()=>{
|
||||
const iH = $win.height(),
|
||||
iW = $win.height();
|
||||
(()=>{
|
||||
const iH = $win.height(),
|
||||
iW = $win.height();
|
||||
|
||||
if ($win.__sizes[0] !== iH || $win.__sizes[1] !== iW) {
|
||||
$win.__sizes[0] = iH;
|
||||
$win.__sizes[1] = iW;
|
||||
dispatchEvent(new CustomEvent('resize.real'));
|
||||
}
|
||||
t = 0;
|
||||
}, 50);
|
||||
if ($win.__sizes[0] !== iH || $win.__sizes[1] !== iW) {
|
||||
$win.__sizes[0] = iH;
|
||||
$win.__sizes[1] = iW;
|
||||
dispatchEvent(new CustomEvent('resize.real'));
|
||||
}
|
||||
}
|
||||
}).throttle(50)
|
||||
);
|
||||
|
||||
const $doc = document;
|
||||
|
@ -64,12 +57,7 @@ class AbstractApp extends AbstractBoot {
|
|||
}
|
||||
});
|
||||
|
||||
var d;
|
||||
const fn = ()=>{
|
||||
// debounce
|
||||
clearTimeout(d);
|
||||
d = setTimeout(()=>dispatchEvent(new CustomEvent('rl.auto-logout-refresh')), 5000);
|
||||
}
|
||||
const fn = (()=>dispatchEvent(new CustomEvent('rl.auto-logout-refresh'))).debounce(5000);
|
||||
|
||||
$doc.addEventListener('mousemove', fn);
|
||||
$doc.addEventListener('keypress', fn);
|
||||
|
|
|
@ -81,16 +81,14 @@ import { AbstractApp } from 'App/Abstract';
|
|||
const doc = document;
|
||||
|
||||
if (!window.ResizeObserver) {
|
||||
let rot;
|
||||
window.ResizeObserver = class {
|
||||
constructor(callback) {
|
||||
callback = callback.debounce(250);
|
||||
this.observer = new MutationObserver(mutations => {
|
||||
let i = mutations.length;
|
||||
while (i--) {
|
||||
if ('style' == mutations[i].attributeName) {
|
||||
// debounce
|
||||
clearTimeout(rot);
|
||||
rot = setTimeout(callback, 250);
|
||||
callback();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -113,15 +111,11 @@ class AppUser extends AbstractApp {
|
|||
|
||||
this.moveCache = {};
|
||||
|
||||
let qd, o = this;
|
||||
this.quotaDebounce = ()=>{
|
||||
// debounce
|
||||
clearTimeout(qd);
|
||||
qd = setTimeout(o.quota, 30000);
|
||||
};
|
||||
|
||||
this.quotaDebounce = this.quota.debounce(30000);
|
||||
this.moveOrDeleteResponseHelper = this.moveOrDeleteResponseHelper.bind(this);
|
||||
|
||||
this.messagesMoveTrigger = this.messagesMoveTrigger.debounce(500);
|
||||
|
||||
// wakeUp
|
||||
const interval = 3600000; // 60m
|
||||
var lastTime = (new Date()).getTime();
|
||||
|
@ -262,30 +256,25 @@ class AppUser extends AbstractApp {
|
|||
}
|
||||
|
||||
messagesMoveTrigger() {
|
||||
// debounce
|
||||
const o = this;
|
||||
clearTimeout(o.mt);
|
||||
o.mt = setTimeout(()=>{
|
||||
const sTrashFolder = FolderStore.trashFolder(),
|
||||
sSpamFolder = FolderStore.spamFolder();
|
||||
const sTrashFolder = FolderStore.trashFolder(),
|
||||
sSpamFolder = FolderStore.spamFolder();
|
||||
|
||||
Object.values(o.moveCache).forEach(item => {
|
||||
const isSpam = sSpamFolder === item.To,
|
||||
isTrash = sTrashFolder === item.To,
|
||||
isHam = !isSpam && sSpamFolder === item.From && getFolderInboxName() === item.To;
|
||||
Object.values(this.moveCache).forEach(item => {
|
||||
const isSpam = sSpamFolder === item.To,
|
||||
isTrash = sTrashFolder === item.To,
|
||||
isHam = !isSpam && sSpamFolder === item.From && getFolderInboxName() === item.To;
|
||||
|
||||
Remote.messagesMove(
|
||||
o.moveOrDeleteResponseHelper,
|
||||
item.From,
|
||||
item.To,
|
||||
item.Uid,
|
||||
isSpam ? 'SPAM' : isHam ? 'HAM' : '',
|
||||
isSpam || isTrash
|
||||
);
|
||||
});
|
||||
Remote.messagesMove(
|
||||
this.moveOrDeleteResponseHelper,
|
||||
item.From,
|
||||
item.To,
|
||||
item.Uid,
|
||||
isSpam ? 'SPAM' : isHam ? 'HAM' : '',
|
||||
isSpam || isTrash
|
||||
);
|
||||
});
|
||||
|
||||
o.moveCache = {};
|
||||
}, 500);
|
||||
this.moveCache = {};
|
||||
}
|
||||
|
||||
messagesMoveHelper(fromFolderFullNameRaw, toFolderFullNameRaw, uidsForMove) {
|
||||
|
|
|
@ -145,7 +145,7 @@ class CookieDriver {
|
|||
|
||||
try {
|
||||
const storageResult = Cookies.getJSON(CLIENT_SIDE_STORAGE_INDEX_NAME);
|
||||
result = storageResult && undefined !== storageResult[key] ? storageResult[key] : null;
|
||||
result = storageResult && null != storageResult[key] ? storageResult[key] : null;
|
||||
} catch (e) {} // eslint-disable-line no-empty
|
||||
|
||||
return result;
|
||||
|
|
|
@ -47,7 +47,7 @@ class LocalStorageDriver {
|
|||
const storageValue = this.s.getItem(CLIENT_SIDE_STORAGE_INDEX_NAME) || null,
|
||||
storageResult = null === storageValue ? null : JSON.parse(storageValue);
|
||||
|
||||
return storageResult && undefined !== storageResult[key] ? storageResult[key] : null;
|
||||
return storageResult && null != storageResult[key] ? storageResult[key] : null;
|
||||
} catch (e) {} // eslint-disable-line no-empty
|
||||
|
||||
return null;
|
||||
|
|
|
@ -32,16 +32,7 @@ class HtmlEditor {
|
|||
this.element = element;
|
||||
this.$element = jQuery(element);
|
||||
|
||||
// throttle
|
||||
var t, o = this;
|
||||
this.resize = ()=>{
|
||||
if (!t) {
|
||||
t = setTimeout(()=>{
|
||||
o.resizeEditor();
|
||||
t = 0;
|
||||
}, 100);
|
||||
}
|
||||
};
|
||||
this.resize = this.resizeEditor.throttle(100);
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
|
|
@ -88,6 +88,6 @@ export function runSettingsViewModelHooks(admin) {
|
|||
*/
|
||||
export function settingsGet(pluginSection, name) {
|
||||
let plugins = Settings.settingsGet('Plugins');
|
||||
plugins = plugins && undefined !== plugins[pluginSection] ? plugins[pluginSection] : null;
|
||||
return plugins ? (undefined === plugins[name] ? null : plugins[name]) : null;
|
||||
plugins = plugins && null != plugins[pluginSection] ? plugins[pluginSection] : null;
|
||||
return plugins ? (null == plugins[name] ? null : plugins[name]) : null;
|
||||
}
|
||||
|
|
|
@ -52,12 +52,7 @@ class Selector {
|
|||
this.focusedItem = koFocusedItem || ko.observable(null);
|
||||
this.selectedItem = koSelectedItem || ko.observable(null);
|
||||
|
||||
var d, o = this;
|
||||
this.itemSelectedThrottle = (item)=>{
|
||||
// debounce
|
||||
clearTimeout(d);
|
||||
d = setTimeout(()=>o.itemSelected(item), 300);
|
||||
};
|
||||
this.itemSelectedThrottle = (item=>this.itemSelected(item)).debounce(300);
|
||||
|
||||
this.listChecked.subscribe((items) => {
|
||||
if (items.length) {
|
||||
|
|
|
@ -94,7 +94,7 @@ export function i18n(key, valueList, defaulValue) {
|
|||
result = undefined === defaulValue ? key : defaulValue;
|
||||
}
|
||||
|
||||
if (undefined !== valueList && null !== valueList) {
|
||||
if (null != valueList) {
|
||||
for (valueName in valueList) {
|
||||
if (Object.prototype.hasOwnProperty.call(valueList, valueName)) {
|
||||
result = result.replace('%' + valueName + '%', valueList[valueName]);
|
||||
|
|
|
@ -124,17 +124,6 @@ export function splitPlainText(text, len = 100) {
|
|||
return prefix + result;
|
||||
}
|
||||
|
||||
const timeOutAction = (() => {
|
||||
const timeOuts = {};
|
||||
return (action, fFunction, timeOut) => {
|
||||
timeOuts[action] = undefined === timeOuts[action] ? 0 : timeOuts[action];
|
||||
clearTimeout(timeOuts[action]);
|
||||
timeOuts[action] = setTimeout(fFunction, timeOut);
|
||||
};
|
||||
})();
|
||||
|
||||
export { timeOutAction };
|
||||
|
||||
/**
|
||||
* @param {any} m
|
||||
* @returns {any}
|
||||
|
@ -258,27 +247,6 @@ export function friendlySize(sizeInBytes) {
|
|||
return sizeInBytes + 'B';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {?} object
|
||||
* @param {string} methodName
|
||||
* @param {Array=} params
|
||||
* @param {number=} delay = 0
|
||||
*/
|
||||
export function delegateRun(object, methodName, params, delay = 0) {
|
||||
if (object && object[methodName]) {
|
||||
delay = pInt(delay);
|
||||
params = isArray(params) ? params : [];
|
||||
|
||||
if (0 >= delay) {
|
||||
object[methodName](...params);
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
object[methodName](...params);
|
||||
}, delay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {(Object|null|undefined)} context
|
||||
* @param {Function} fExecute
|
||||
|
@ -830,14 +798,9 @@ export function selectElement(element) {
|
|||
sel.addRange(range);
|
||||
}
|
||||
|
||||
var dv;
|
||||
export const detectDropdownVisibility = ()=>{
|
||||
// leading debounce
|
||||
clearTimeout(dv);
|
||||
dv = setTimeout(()=>
|
||||
dropdownVisibility(!!GlobalsData.aBootstrapDropdowns.find(item => item.hasClass('open')))
|
||||
, 50);
|
||||
};
|
||||
export const detectDropdownVisibility = (()=>
|
||||
dropdownVisibility(!!GlobalsData.aBootstrapDropdowns.find(item => item.hasClass('open')))
|
||||
).debounce(50);
|
||||
|
||||
/**
|
||||
* @param {boolean=} delay = false
|
||||
|
@ -881,11 +844,9 @@ export function getConfigurationFromScriptTag(configuration) {
|
|||
export function delegateRunOnDestroy(objectOrObjects) {
|
||||
if (objectOrObjects) {
|
||||
if (isArray(objectOrObjects)) {
|
||||
objectOrObjects.forEach(item => {
|
||||
delegateRunOnDestroy(item);
|
||||
});
|
||||
} else if (objectOrObjects && objectOrObjects.onDestroy) {
|
||||
objectOrObjects.onDestroy();
|
||||
objectOrObjects.forEach(item => delegateRunOnDestroy(item));
|
||||
} else {
|
||||
objectOrObjects.onDestroy && objectOrObjects.onDestroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1199,8 +1160,8 @@ export function mailToHelper(mailToUrl, PopupComposeViewModel) {
|
|||
to,
|
||||
cc,
|
||||
bcc,
|
||||
undefined === params.subject ? null : pString(decodeURIComponent(params.subject)),
|
||||
undefined === params.body ? null : plainToHtml(pString(decodeURIComponent(params.body)))
|
||||
null == params.subject ? null : pString(decodeURIComponent(params.subject)),
|
||||
null == params.body ? null : plainToHtml(pString(decodeURIComponent(params.body)))
|
||||
]);
|
||||
|
||||
return true;
|
||||
|
@ -1212,7 +1173,7 @@ export function mailToHelper(mailToUrl, PopupComposeViewModel) {
|
|||
var wr;
|
||||
export const windowResize = timeout => {
|
||||
clearTimeout(wr);
|
||||
if (undefined === timeout || null === timeout) {
|
||||
if (null == timeout) {
|
||||
$win.trigger('resize');
|
||||
} else {
|
||||
wr = setTimeout(()=>$win.trigger('resize'), timeout);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import ko from 'ko';
|
||||
|
||||
import { delegateRun, inFocus } from 'Common/Utils';
|
||||
import { inFocus } from 'Common/Utils';
|
||||
import { KeyState, EventKeyCode } from 'Common/Enums';
|
||||
import { keyScope } from 'Common/Globals';
|
||||
|
||||
|
@ -38,7 +38,7 @@ export class AbstractViewNext {
|
|||
addEventListener('keydown', (event) => {
|
||||
if (event && this.modalVisibility && this.modalVisibility()) {
|
||||
if (!this.bDisabeCloseOnEsc && EventKeyCode.Esc === event.keyCode) {
|
||||
delegateRun(this, 'cancelCommand');
|
||||
this.cancelCommand && this.cancelCommand();
|
||||
return false;
|
||||
} else if (EventKeyCode.Backspace === event.keyCode && !inFocus()) {
|
||||
return false;
|
||||
|
|
|
@ -3,7 +3,7 @@ import ko from 'ko';
|
|||
import { runHook } from 'Common/Plugins';
|
||||
import { $htmlCL, VIEW_MODELS, popupVisibilityNames } from 'Common/Globals';
|
||||
|
||||
import { pString, createCommandLegacy, delegateRun, isNonEmptyArray } from 'Common/Utils';
|
||||
import { pString, createCommandLegacy, isNonEmptyArray } from 'Common/Utils';
|
||||
|
||||
let currentScreen = null,
|
||||
defaultScreenName = '';
|
||||
|
@ -90,7 +90,7 @@ export function routeOn() {
|
|||
* @returns {?Object}
|
||||
*/
|
||||
export function screen(screenName) {
|
||||
return screenName && undefined !== SCREENS[screenName] ? SCREENS[screenName] : null;
|
||||
return screenName && null != SCREENS[screenName] ? SCREENS[screenName] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -181,10 +181,10 @@ export function buildViewModel(ViewModelClass, vmScreen) {
|
|||
vm.onShowTrigger(!vm.onShowTrigger());
|
||||
}
|
||||
|
||||
delegateRun(vm, 'onShowWithDelay', [], 500);
|
||||
vm.onShowWithDelay && setTimeout(()=>vm.onShowWithDelay, 500);
|
||||
} else {
|
||||
delegateRun(vm, 'onHide');
|
||||
delegateRun(vm, 'onHideWithDelay', [], 500);
|
||||
vm.onHide && vm.onHide();
|
||||
vm.onHideWithDelay && setTimeout(()=>vm.onHideWithDelay, 500);
|
||||
|
||||
if (vm.onHideTrigger) {
|
||||
vm.onHideTrigger(!vm.onHideTrigger());
|
||||
|
@ -213,7 +213,7 @@ export function buildViewModel(ViewModelClass, vmScreen) {
|
|||
vm
|
||||
);
|
||||
|
||||
delegateRun(vm, 'onBuild', [vmDom]);
|
||||
vm.onBuild && vm.onBuild(vmDom);
|
||||
if (vm && ViewType.Popup === position) {
|
||||
vm.registerPopupKeyDown();
|
||||
}
|
||||
|
@ -238,11 +238,13 @@ export function showScreenPopup(ViewModelClassToShow, params = []) {
|
|||
buildViewModel(ModalView);
|
||||
|
||||
if (ModalView.__vm && ModalView.__dom) {
|
||||
delegateRun(ModalView.__vm, 'onBeforeShow', params || []);
|
||||
params = params || [];
|
||||
|
||||
ModalView.__vm.onBeforeShow && ModalView.__vm.onBeforeShow(...params);
|
||||
|
||||
ModalView.__vm.modalVisibility(true);
|
||||
|
||||
delegateRun(ModalView.__vm, 'onShow', params || []);
|
||||
ModalView.__vm.onShow && ModalView.__vm.onShow(...params);
|
||||
|
||||
vmRunHook('view-model-on-show', ModalView, params || []);
|
||||
}
|
||||
|
@ -259,7 +261,7 @@ export function warmUpScreenPopup(ViewModelClassToShow) {
|
|||
buildViewModel(ModalView);
|
||||
|
||||
if (ModalView.__vm && ModalView.__dom) {
|
||||
delegateRun(ModalView.__vm, 'onWarmUp');
|
||||
ModalView.__vm.onWarmUp && ModalView.__vm.onWarmUp();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -309,14 +311,14 @@ export function screenOnRoute(screenName, subPart) {
|
|||
});
|
||||
}
|
||||
|
||||
delegateRun(vmScreen, 'onBuild');
|
||||
vmScreen.onBuild && vmScreen.onBuild();
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
// hide screen
|
||||
if (currentScreen && !isSameScreen) {
|
||||
delegateRun(currentScreen, 'onHide');
|
||||
delegateRun(currentScreen, 'onHideWithDelay', [], 500);
|
||||
currentScreen.onHide && currentScreen.onHide();
|
||||
currentScreen.onHideWithDelay && setTimeout(()=>currentScreen.onHideWithDelay(), 500);
|
||||
|
||||
if (currentScreen.onHideTrigger) {
|
||||
currentScreen.onHideTrigger(!currentScreen.onHideTrigger());
|
||||
|
@ -332,8 +334,8 @@ export function screenOnRoute(screenName, subPart) {
|
|||
ViewModelClass.__dom.hide();
|
||||
ViewModelClass.__vm.viewModelVisibility(false);
|
||||
|
||||
delegateRun(ViewModelClass.__vm, 'onHide');
|
||||
delegateRun(ViewModelClass.__vm, 'onHideWithDelay', [], 500);
|
||||
ViewModelClass.__vm.onHide && ViewModelClass.__vm.onHide();
|
||||
ViewModelClass.__vm.onHideWithDelay && setTimeout(()=>ViewModelClass.__vm.onHideWithDelay(), 500);
|
||||
|
||||
if (ViewModelClass.__vm.onHideTrigger) {
|
||||
ViewModelClass.__vm.onHideTrigger(!ViewModelClass.__vm.onHideTrigger());
|
||||
|
@ -348,7 +350,7 @@ export function screenOnRoute(screenName, subPart) {
|
|||
|
||||
// show screen
|
||||
if (currentScreen && !isSameScreen) {
|
||||
delegateRun(currentScreen, 'onShow');
|
||||
currentScreen.onShow && currentScreen.onShow();
|
||||
if (currentScreen.onShowTrigger) {
|
||||
currentScreen.onShowTrigger(!currentScreen.onShowTrigger());
|
||||
}
|
||||
|
@ -362,17 +364,18 @@ export function screenOnRoute(screenName, subPart) {
|
|||
ViewModelClass.__dom &&
|
||||
ViewType.Popup !== ViewModelClass.__vm.viewModelPosition
|
||||
) {
|
||||
delegateRun(ViewModelClass.__vm, 'onBeforeShow');
|
||||
ViewModelClass.__vm.onBeforeShow && ViewModelClass.__vm.onBeforeShow();
|
||||
|
||||
ViewModelClass.__dom.show();
|
||||
ViewModelClass.__vm.viewModelVisibility(true);
|
||||
|
||||
delegateRun(ViewModelClass.__vm, 'onShow');
|
||||
ViewModelClass.__vm.onShow && ViewModelClass.__vm.onShow();
|
||||
if (ViewModelClass.__vm.onShowTrigger) {
|
||||
ViewModelClass.__vm.onShowTrigger(!ViewModelClass.__vm.onShowTrigger());
|
||||
}
|
||||
|
||||
delegateRun(ViewModelClass.__vm, 'onShowWithDelay', [], 200);
|
||||
ViewModelClass.__vm.onShowWithDelay && setTimeout(()=>ViewModelClass.__vm.onShowWithDelay, 200);
|
||||
|
||||
vmRunHook('view-model-on-show', ViewModelClass);
|
||||
}
|
||||
});
|
||||
|
@ -415,7 +418,7 @@ export function startScreens(screensClasses) {
|
|||
vmScreen.__start();
|
||||
|
||||
runHook('screen-pre-start', [vmScreen.screenName(), vmScreen]);
|
||||
delegateRun(vmScreen, 'onStart');
|
||||
vmScreen.onStart && vmScreen.onStart();
|
||||
runHook('screen-post-start', [vmScreen.screenName(), vmScreen]);
|
||||
}
|
||||
});
|
||||
|
@ -526,30 +529,23 @@ function commandDecorator(canExecute = true) {
|
|||
* @returns {Function}
|
||||
*/
|
||||
function settingsMenuKeysHandler($items) {
|
||||
// throttle
|
||||
var t;
|
||||
return (event, handler)=>{
|
||||
if (!t) {
|
||||
t = setTimeout(()=>{
|
||||
const up = handler && 'up' === handler.shortcut;
|
||||
return ((event, handler)=>{
|
||||
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);
|
||||
}
|
||||
}
|
||||
t = 0;
|
||||
}, 200);
|
||||
const resultHash = $items.eq(index).attr('href');
|
||||
if (resultHash) {
|
||||
setHash(resultHash, false, true);
|
||||
}
|
||||
}
|
||||
};
|
||||
}).throttle(200);
|
||||
}
|
||||
|
||||
export {
|
||||
|
|
|
@ -37,7 +37,7 @@ class AbstractAjaxPromises extends AbstractBasicPromises {
|
|||
|
||||
ajaxRequest(action, isPost, timeOut, params, additionalGetString, fTrigger) {
|
||||
|
||||
additionalGetString = undefined === additionalGetString ? '' : pString(additionalGetString);
|
||||
additionalGetString = pString(additionalGetString);
|
||||
|
||||
let init = {
|
||||
mode: 'same-origin',
|
||||
|
@ -65,7 +65,7 @@ class AbstractAjaxPromises extends AbstractBasicPromises {
|
|||
}
|
||||
};
|
||||
buildFormData(formData, params);
|
||||
init.body = (new URLSearchParams(formData)).toString();
|
||||
init.body = new URLSearchParams(formData);
|
||||
}
|
||||
|
||||
runHook('ajax-default-request', [action, params, additionalGetString]);
|
||||
|
|
|
@ -163,7 +163,7 @@ class AbstractAjaxRemote {
|
|||
}
|
||||
};
|
||||
buildFormData(formData, params);
|
||||
init.body = (new URLSearchParams(formData)).toString();
|
||||
init.body = new URLSearchParams(formData);
|
||||
}
|
||||
|
||||
if (window.AbortController) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import ko from 'ko';
|
||||
|
||||
import { VIEW_MODELS } from 'Common/Globals';
|
||||
import { delegateRun, windowResize, pString } from 'Common/Utils';
|
||||
import { windowResize, pString } from 'Common/Utils';
|
||||
import { settings } from 'Common/Links';
|
||||
|
||||
import { setHash } from 'Knoin/Knoin';
|
||||
|
@ -94,7 +94,7 @@ class AbstractSettingsScreen extends AbstractScreen {
|
|||
settingsScreen
|
||||
);
|
||||
|
||||
delegateRun(settingsScreen, 'onBuild', [viewModelDom]);
|
||||
settingsScreen.onBuild && settingsScreen.onBuild(viewModelDom);
|
||||
} else {
|
||||
console.log('Cannot find sub settings view model position: SettingsSubScreen');
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ class AbstractSettingsScreen extends AbstractScreen {
|
|||
setTimeout(() => {
|
||||
// hide
|
||||
if (o.oCurrentSubScreen) {
|
||||
delegateRun(o.oCurrentSubScreen, 'onHide');
|
||||
o.oCurrentSubScreen.onHide && o.oCurrentSubScreen.onHide();
|
||||
o.oCurrentSubScreen.viewModelDom.hide();
|
||||
}
|
||||
// --
|
||||
|
@ -114,10 +114,10 @@ class AbstractSettingsScreen extends AbstractScreen {
|
|||
|
||||
// show
|
||||
if (o.oCurrentSubScreen) {
|
||||
delegateRun(o.oCurrentSubScreen, 'onBeforeShow');
|
||||
o.oCurrentSubScreen.onBeforeShow && o.oCurrentSubScreen.onBeforeShow();
|
||||
o.oCurrentSubScreen.viewModelDom.show();
|
||||
delegateRun(o.oCurrentSubScreen, 'onShow');
|
||||
delegateRun(o.oCurrentSubScreen, 'onShowWithDelay', [], 200);
|
||||
o.oCurrentSubScreen.onShow && o.oCurrentSubScreen.onShow();
|
||||
o.oCurrentSubScreen.onShowWithDelay && setTimeout(() => o.oCurrentSubScreen.onShowWithDelay(), 200);
|
||||
|
||||
o.menu().forEach(item => {
|
||||
item.selected(
|
||||
|
@ -141,7 +141,7 @@ class AbstractSettingsScreen extends AbstractScreen {
|
|||
|
||||
onHide() {
|
||||
if (this.oCurrentSubScreen && this.oCurrentSubScreen.viewModelDom) {
|
||||
delegateRun(this.oCurrentSubScreen, 'onHide');
|
||||
this.oCurrentSubScreen.onHide && this.oCurrentSubScreen.onHide();
|
||||
this.oCurrentSubScreen.viewModelDom.hide();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import { MESSAGES_PER_PAGE_VALUES } from 'Common/Consts';
|
|||
|
||||
import { SaveSettingsStep, EditorDefaultType, Layout } from 'Common/Enums';
|
||||
|
||||
import { settingsSaveHelperSimpleFunction, convertLangName, timeOutAction } from 'Common/Utils';
|
||||
import { settingsSaveHelperSimpleFunction, convertLangName } from 'Common/Utils';
|
||||
|
||||
import { i18n, trigger as translatorTrigger, reload as translatorReload } from 'Common/Translator';
|
||||
|
||||
|
@ -121,46 +121,28 @@ class GeneralUserSettings {
|
|||
|
||||
this.useCheckboxesInList.subscribe(Remote.saveSettingsHelper('UseCheckboxesInList', v=>v?'1':'0'));
|
||||
|
||||
this.enableDesktopNotification.subscribe((value) => {
|
||||
timeOutAction(
|
||||
'SaveDesktopNotifications',
|
||||
() => {
|
||||
Remote.saveSettings(null, {
|
||||
'DesktopNotifications': value ? '1' : '0'
|
||||
});
|
||||
},
|
||||
3000
|
||||
);
|
||||
});
|
||||
this.enableDesktopNotification.subscribe((value =>
|
||||
Remote.saveSettings(null, {
|
||||
'DesktopNotifications': value ? 1 : 0
|
||||
})
|
||||
).debounce(3000));
|
||||
|
||||
this.enableSoundNotification.subscribe((value) => {
|
||||
timeOutAction(
|
||||
'SaveSoundNotification',
|
||||
() => {
|
||||
Remote.saveSettings(null, {
|
||||
'SoundNotification': value ? '1' : '0'
|
||||
});
|
||||
},
|
||||
3000
|
||||
);
|
||||
});
|
||||
this.enableSoundNotification.subscribe((value =>
|
||||
Remote.saveSettings(null, {
|
||||
'SoundNotification': value ? 1 : 0
|
||||
})
|
||||
).debounce(3000));
|
||||
|
||||
this.replySameFolder.subscribe((value) => {
|
||||
timeOutAction(
|
||||
'SaveReplySameFolder',
|
||||
() => {
|
||||
Remote.saveSettings(null, {
|
||||
'ReplySameFolder': value ? '1' : '0'
|
||||
});
|
||||
},
|
||||
3000
|
||||
);
|
||||
});
|
||||
this.replySameFolder.subscribe((value =>
|
||||
Remote.saveSettings(null, {
|
||||
'ReplySameFolder': value ? 1 : 0
|
||||
})
|
||||
).debounce(3000));
|
||||
|
||||
this.useThreads.subscribe((value) => {
|
||||
MessageStore.messageList([]);
|
||||
Remote.saveSettings(null, {
|
||||
'UseThreads': value ? '1' : '0'
|
||||
'UseThreads': value ? 1 : 0
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ APP_SETTINGS = null != APP_SETTINGS ? APP_SETTINGS : {};
|
|||
* @returns {*}
|
||||
*/
|
||||
export function settingsGet(name) {
|
||||
return undefined === SETTINGS[name] ? null : SETTINGS[name];
|
||||
return null == SETTINGS[name] ? null : SETTINGS[name];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -25,7 +25,7 @@ export function settingsSet(name, value) {
|
|||
* @returns {*}
|
||||
*/
|
||||
export function appSettingsGet(name) {
|
||||
return undefined === APP_SETTINGS[name] ? null : APP_SETTINGS[name];
|
||||
return null == APP_SETTINGS[name] ? null : APP_SETTINGS[name];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -112,16 +112,7 @@ class MessageUserStore {
|
|||
|
||||
this.onMessageResponse = this.onMessageResponse.bind(this);
|
||||
|
||||
// throttle
|
||||
var t, o = this;
|
||||
this.purgeMessageBodyCacheThrottle = ()=>{
|
||||
if (!t) {
|
||||
t = setTimeout(()=>{
|
||||
o.purgeMessageBodyCache();
|
||||
t = 0;
|
||||
}, 30000);
|
||||
}
|
||||
};
|
||||
this.purgeMessageBodyCacheThrottle = this.purgeMessageBodyCache.throttle(30000);
|
||||
}
|
||||
|
||||
computers() {
|
||||
|
@ -203,20 +194,15 @@ class MessageUserStore {
|
|||
this.messageListCompleteLoadingThrottleForAnimation(value);
|
||||
});
|
||||
|
||||
var d;
|
||||
this.messageList.subscribe(
|
||||
(list)=>{
|
||||
// debounce
|
||||
clearTimeout(d);
|
||||
d = setTimeout(()=>list.forEach(item => {
|
||||
if (item && item.newForAnimation()) {
|
||||
item.newForAnimation(false);
|
||||
}
|
||||
}), 500);
|
||||
}
|
||||
(list=> {
|
||||
list.forEach(item =>
|
||||
item && item.newForAnimation() && item.newForAnimation(false)
|
||||
)
|
||||
}).debounce(500)
|
||||
);
|
||||
|
||||
this.message.subscribe((message) => {
|
||||
this.message.subscribe(message => {
|
||||
if (message) {
|
||||
if (Layout.NoPreview === SettingsStore.layout()) {
|
||||
AppStore.focusedState(Focused.MessageView);
|
||||
|
@ -229,9 +215,7 @@ class MessageUserStore {
|
|||
}
|
||||
});
|
||||
|
||||
this.messageLoading.subscribe((value) => {
|
||||
this.messageLoadingThrottle(value);
|
||||
});
|
||||
this.messageLoading.subscribe(value => this.messageLoadingThrottle(value));
|
||||
|
||||
this.messagesBodiesDom.subscribe((dom) => {
|
||||
if (dom && !(dom instanceof $)) {
|
||||
|
@ -239,7 +223,7 @@ class MessageUserStore {
|
|||
}
|
||||
});
|
||||
|
||||
this.messageListEndFolder.subscribe((folder) => {
|
||||
this.messageListEndFolder.subscribe(folder => {
|
||||
const message = this.message();
|
||||
if (message && folder && folder !== message.folderFullNameRaw) {
|
||||
this.message(null);
|
||||
|
@ -745,7 +729,7 @@ class MessageUserStore {
|
|||
iCount = pInt(data.Result.MessageResultCount),
|
||||
iOffset = pInt(data.Result.Offset);
|
||||
|
||||
const folder = getFolderFromCacheList(null != data.Result.Folder ? data.Result.Folder : '');
|
||||
const folder = getFolderFromCacheList(data.Result.Folder);
|
||||
|
||||
if (folder && !cached) {
|
||||
folder.interval = Date.now() / 1000;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import ko from 'ko';
|
||||
import { delegateRun } from 'Common/Utils';
|
||||
|
||||
import PgpStore from 'Stores/User/Pgp';
|
||||
|
||||
|
@ -83,7 +82,7 @@ class AddOpenPgpKeyPopupView extends AbstractViewNext {
|
|||
return false;
|
||||
}
|
||||
|
||||
delegateRun(this, 'cancelCommand');
|
||||
this.cancelCommand && this.cancelCommand();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ import {
|
|||
} from 'Common/Enums';
|
||||
|
||||
import {
|
||||
delegateRun,
|
||||
isNonEmptyArray,
|
||||
clearBqSwitcher,
|
||||
replySubjectAdd,
|
||||
|
@ -85,7 +84,7 @@ class ComposePopupView extends AbstractViewNext {
|
|||
|
||||
this.sLastFocusedField = 'to';
|
||||
|
||||
this.resizerTrigger = this.resizerTrigger.bind(this);
|
||||
this.resizerTrigger = this.resizerTrigger.debounce(50).bind(this);
|
||||
|
||||
this.allowContacts = !!AppStore.contactsIsAllowed();
|
||||
this.allowFolders = !!Settings.capa(Capa.Folders);
|
||||
|
@ -148,17 +147,9 @@ class ComposePopupView extends AbstractViewNext {
|
|||
}
|
||||
});
|
||||
|
||||
this.savedError.subscribe((value) => {
|
||||
if (!value) {
|
||||
this.savedErrorDesc('');
|
||||
}
|
||||
});
|
||||
this.savedError.subscribe(value => !value && this.savedErrorDesc(''));
|
||||
|
||||
this.sendSuccessButSaveError.subscribe((value) => {
|
||||
if (!value) {
|
||||
this.savedErrorDesc('');
|
||||
}
|
||||
});
|
||||
this.sendSuccessButSaveError.subscribe(value => !value && this.savedErrorDesc(''));
|
||||
|
||||
this.savedTime = ko.observable(0);
|
||||
this.savedTimeText = ko.computed(() =>
|
||||
|
@ -297,9 +288,6 @@ class ComposePopupView extends AbstractViewNext {
|
|||
|
||||
this.canBeSentOrSaved = ko.computed(() => !this.sending() && !this.saving());
|
||||
|
||||
this.sendMessageResponse = this.sendMessageResponse.bind(this);
|
||||
this.saveMessageResponse = this.saveMessageResponse.bind(this);
|
||||
|
||||
setInterval(() => {
|
||||
if (
|
||||
this.modalVisibility() &&
|
||||
|
@ -318,20 +306,10 @@ class ComposePopupView extends AbstractViewNext {
|
|||
this.showBcc.subscribe(this.resizerTrigger);
|
||||
this.showReplyTo.subscribe(this.resizerTrigger);
|
||||
|
||||
this.onMessageUploadAttachments = this.onMessageUploadAttachments.bind(this);
|
||||
|
||||
this.bDisabeCloseOnEsc = true;
|
||||
this.sDefaultKeyScope = KeyState.Compose;
|
||||
|
||||
// debounce
|
||||
var d, fn = this.tryToClosePopup.bind(this);
|
||||
this.tryToClosePopup = ()=>{
|
||||
clearTimeout(d);
|
||||
d = setTimeout(fn, 200);
|
||||
};
|
||||
|
||||
this.emailsSource = this.emailsSource.bind(this);
|
||||
this.autosaveFunction = this.autosaveFunction.bind(this);
|
||||
this.tryToClosePopup = this.tryToClosePopup.debounce(200);
|
||||
|
||||
this.iTimer = 0;
|
||||
}
|
||||
|
@ -424,7 +402,7 @@ class ComposePopupView extends AbstractViewNext {
|
|||
setFolderHash(sSentFolder, '');
|
||||
|
||||
Remote.sendMessage(
|
||||
this.sendMessageResponse,
|
||||
this.sendMessageResponse.bind(this),
|
||||
this.getMessageRequestParams(sSentFolder)
|
||||
);
|
||||
}
|
||||
|
@ -448,7 +426,7 @@ class ComposePopupView extends AbstractViewNext {
|
|||
setFolderHash(FolderStore.draftFolder(), '');
|
||||
|
||||
Remote.saveMessage(
|
||||
this.saveMessageResponse,
|
||||
this.saveMessageResponse.bind(this),
|
||||
this.getMessageRequestParams(FolderStore.draftFolder())
|
||||
);
|
||||
}
|
||||
|
@ -517,7 +495,7 @@ class ComposePopupView extends AbstractViewNext {
|
|||
|
||||
autosaveStart() {
|
||||
clearTimeout(this.iTimer);
|
||||
this.iTimer = setTimeout(this.autosaveFunction, 60000);
|
||||
this.iTimer = setTimeout(()=>this.autosaveFunction(), 60000);
|
||||
}
|
||||
|
||||
autosaveStop() {
|
||||
|
@ -525,9 +503,7 @@ class ComposePopupView extends AbstractViewNext {
|
|||
}
|
||||
|
||||
emailsSource(oData, fResponse) {
|
||||
getApp().getAutocomplete(oData.term, (aData) => {
|
||||
fResponse(aData.map(oEmailItem => oEmailItem.toLine(false)));
|
||||
});
|
||||
getApp().getAutocomplete(oData.term, aData => fResponse(aData.map(oEmailItem => oEmailItem.toLine(false))));
|
||||
}
|
||||
|
||||
openOpenPgpPopup() {
|
||||
|
@ -615,9 +591,7 @@ class ComposePopupView extends AbstractViewNext {
|
|||
|
||||
if (StorageResultType.Success === statusResult && data && data.Result) {
|
||||
result = true;
|
||||
if (this.modalVisibility()) {
|
||||
delegateRun(this, 'closeCommand');
|
||||
}
|
||||
this.modalVisibility() && this.closeCommand && this.closeCommand();
|
||||
}
|
||||
|
||||
if (this.modalVisibility() && !result) {
|
||||
|
@ -1096,7 +1070,7 @@ class ComposePopupView extends AbstractViewNext {
|
|||
|
||||
const downloads = this.getAttachmentsDownloadsForUpload();
|
||||
if (isNonEmptyArray(downloads)) {
|
||||
Remote.messageUploadAttachments(this.onMessageUploadAttachments, downloads);
|
||||
Remote.messageUploadAttachments(()=>this.onMessageUploadAttachments(), downloads);
|
||||
}
|
||||
|
||||
if (identity) {
|
||||
|
@ -1147,13 +1121,13 @@ class ComposePopupView extends AbstractViewNext {
|
|||
const PopupsAskViewModel = require('View/Popup/Ask');
|
||||
if (!isPopupVisible(PopupsAskViewModel) && this.modalVisibility()) {
|
||||
if (this.bSkipNextHide || (this.isEmptyForm() && !this.draftUid())) {
|
||||
delegateRun(this, 'closeCommand');
|
||||
this.closeCommand && this.closeCommand();
|
||||
} else {
|
||||
showScreenPopup(PopupsAskViewModel, [
|
||||
i18n('POPUPS_ASK/DESC_WANT_CLOSE_THIS_WINDOW'),
|
||||
() => {
|
||||
if (this.modalVisibility()) {
|
||||
delegateRun(this, 'closeCommand');
|
||||
this.closeCommand && this.closeCommand();
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
@ -1206,12 +1180,7 @@ class ComposePopupView extends AbstractViewNext {
|
|||
return false;
|
||||
});
|
||||
|
||||
var d, o = this;
|
||||
addEventListener('resize.real', ()=>{
|
||||
// debounce
|
||||
clearTimeout(d);
|
||||
d = setTimeout(o.resizerTrigger, 50);
|
||||
});
|
||||
addEventListener('resize.real', this.resizerTrigger);
|
||||
|
||||
setInterval(() => {
|
||||
if (this.modalVisibility() && this.oEditor) {
|
||||
|
|
|
@ -2,7 +2,7 @@ import ko from 'ko';
|
|||
|
||||
import { FiltersAction, FilterConditionField, FilterConditionType } from 'Common/Enums';
|
||||
import { bMobileDevice } from 'Common/Globals';
|
||||
import { defautOptionsAfterRender, delegateRun } from 'Common/Utils';
|
||||
import { defautOptionsAfterRender } from 'Common/Utils';
|
||||
import { i18n, initOnStartOrLangChange } from 'Common/Translator';
|
||||
|
||||
import FilterStore from 'Stores/User/Filter';
|
||||
|
@ -59,13 +59,9 @@ class FilterPopupView extends AbstractViewNext {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (this.fTrueCallback) {
|
||||
this.fTrueCallback(this.filter());
|
||||
}
|
||||
this.fTrueCallback && this.fTrueCallback(this.filter());
|
||||
|
||||
if (this.modalVisibility()) {
|
||||
delegateRun(this, 'closeCommand');
|
||||
}
|
||||
this.modalVisibility() && this.closeCommand && this.closeCommand();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -55,7 +55,6 @@ 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,21 +62,17 @@ class FolderSystemPopupView extends AbstractViewNext {
|
|||
Settings.settingsSet('TrashFolder', FolderStore.trashFolder());
|
||||
Settings.settingsSet('ArchiveFolder', FolderStore.archiveFolder());
|
||||
},
|
||||
fSaveSystemFolders = ()=>{
|
||||
// debounce
|
||||
clearTimeout(d);
|
||||
d = setTimeout(()=>{
|
||||
fSetSystemFolders();
|
||||
Remote.saveSystemFolders(()=>{}, {
|
||||
SentFolder: FolderStore.sentFolder(),
|
||||
DraftFolder: FolderStore.draftFolder(),
|
||||
SpamFolder: FolderStore.spamFolder(),
|
||||
TrashFolder: FolderStore.trashFolder(),
|
||||
ArchiveFolder: FolderStore.archiveFolder(),
|
||||
NullFolder: 'NullFolder'
|
||||
});
|
||||
}, 1000);
|
||||
},
|
||||
fSaveSystemFolders = (()=>{
|
||||
fSetSystemFolders();
|
||||
Remote.saveSystemFolders(()=>{}, {
|
||||
SentFolder: FolderStore.sentFolder(),
|
||||
DraftFolder: FolderStore.draftFolder(),
|
||||
SpamFolder: FolderStore.spamFolder(),
|
||||
TrashFolder: FolderStore.trashFolder(),
|
||||
ArchiveFolder: FolderStore.archiveFolder(),
|
||||
NullFolder: 'NullFolder'
|
||||
});
|
||||
}).debounce(1000),
|
||||
fCallback = () => {
|
||||
fSetSystemFolders();
|
||||
fSaveSystemFolders();
|
||||
|
|
|
@ -14,39 +14,29 @@ class KeyboardShortcutsHelpPopupView extends AbstractViewNext {
|
|||
}
|
||||
|
||||
onBuild(dom) {
|
||||
var t;
|
||||
key(
|
||||
'tab, shift+tab, left, right',
|
||||
KeyState.PopupKeyboardShortcutsHelp,
|
||||
(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);
|
||||
((event, handler)=>{
|
||||
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;
|
||||
}
|
||||
|
||||
return true;
|
||||
}, 100);
|
||||
$tabs
|
||||
.eq(index)
|
||||
.find('a[data-toggle="tab"]')
|
||||
.tab('show');
|
||||
}
|
||||
}
|
||||
}).throttle(100)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import ko from 'ko';
|
||||
|
||||
import { delegateRun, pInt } from 'Common/Utils';
|
||||
import { pInt } from 'Common/Utils';
|
||||
|
||||
import PgpStore from 'Stores/User/Pgp';
|
||||
|
||||
|
@ -69,7 +69,7 @@ class NewOpenPgpKeyPopupView extends AbstractViewNext {
|
|||
openpgpKeyring.store();
|
||||
|
||||
getApp().reloadOpenPgpKeys();
|
||||
delegateRun(this, 'cancelCommand');
|
||||
this.cancelCommand && this.cancelCommand();
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import ko from 'ko';
|
||||
|
||||
import { KeyState, StorageResultType, Notification } from 'Common/Enums';
|
||||
import { isNonEmptyArray, delegateRun } from 'Common/Utils';
|
||||
import { getNotification, i18n } from 'Common/Translator';
|
||||
|
||||
import Remote from 'Remote/Admin/Ajax';
|
||||
|
@ -41,12 +40,7 @@ class PluginPopupView extends AbstractViewNext {
|
|||
this.bDisabeCloseOnEsc = true;
|
||||
this.sDefaultKeyScope = KeyState.All;
|
||||
|
||||
var d, fn = this.tryToClosePopup.bind(this);
|
||||
this.tryToClosePopup = ()=>{
|
||||
// debounce
|
||||
clearTimeout(d);
|
||||
d = setTimeout(fn, 200);
|
||||
};
|
||||
this.tryToClosePopup = this.tryToClosePopup.debounce(200);
|
||||
}
|
||||
|
||||
@command((self) => self.hasConfiguration())
|
||||
|
@ -89,7 +83,7 @@ class PluginPopupView extends AbstractViewNext {
|
|||
this.readme(oPlugin.Readme);
|
||||
|
||||
const config = oPlugin.Config;
|
||||
if (isNonEmptyArray(config)) {
|
||||
if (Array.isArray(config) && config.length) {
|
||||
this.configures(
|
||||
config.map(item => ({
|
||||
'value': ko.observable(item[0]),
|
||||
|
@ -110,11 +104,7 @@ class PluginPopupView extends AbstractViewNext {
|
|||
if (!isPopupVisible(PopupsAskViewModel)) {
|
||||
showScreenPopup(PopupsAskViewModel, [
|
||||
i18n('POPUPS_ASK/DESC_WANT_CLOSE_THIS_WINDOW'),
|
||||
() => {
|
||||
if (this.modalVisibility()) {
|
||||
delegateRun(this, 'cancelCommand');
|
||||
}
|
||||
}
|
||||
() => this.modalVisibility() && this.cancelCommand && this.cancelCommand()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -539,20 +539,13 @@ class MessageViewMailBoxUserView extends AbstractViewNext {
|
|||
this.showFullInfo.subscribe(fCheckHeaderHeight);
|
||||
this.message.subscribe(fCheckHeaderHeight);
|
||||
|
||||
var t;
|
||||
addEventListener(
|
||||
'resize',
|
||||
()=>{
|
||||
// throttle
|
||||
if (!t) {
|
||||
t = setTimeout(()=>{
|
||||
setTimeout(fCheckHeaderHeight, 1);
|
||||
setTimeout(fCheckHeaderHeight, 200);
|
||||
setTimeout(fCheckHeaderHeight, 500);
|
||||
t = 0;
|
||||
}, 50);
|
||||
}
|
||||
}
|
||||
(()=>{
|
||||
setTimeout(fCheckHeaderHeight, 1);
|
||||
setTimeout(fCheckHeaderHeight, 200);
|
||||
setTimeout(fCheckHeaderHeight, 500);
|
||||
}).throttle(50)
|
||||
);
|
||||
|
||||
this.showFullInfo.subscribe((value) => {
|
||||
|
|
34
dev/prototype-function.js
vendored
Normal file
34
dev/prototype-function.js
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
/**
|
||||
* Every time the function is executed,
|
||||
* it will delay the execution with the given amount of milliseconds.
|
||||
*/
|
||||
if (!Function.prototype.debounce) {
|
||||
Function.prototype.debounce = function(ms) {
|
||||
let func = this, timer;
|
||||
return function(...args) {
|
||||
timer && clearTimeout(timer);
|
||||
timer = setTimeout(()=>{
|
||||
func.apply(this, args)
|
||||
timer = 0;
|
||||
}, ms);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* No matter how many times the event is executed,
|
||||
* the function will be executed only once, after the given amount of milliseconds.
|
||||
*/
|
||||
if (!Function.prototype.throttle) {
|
||||
Function.prototype.throttle = function(ms) {
|
||||
let func = this, timer;
|
||||
return function(...args) {
|
||||
if (!timer) {
|
||||
timer = setTimeout(()=>{
|
||||
func.apply(this, args)
|
||||
timer = 0;
|
||||
}, ms);
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
|
@ -81,6 +81,7 @@ config.paths.js = {
|
|||
'vendors/qr.js/qr.min.js', // fixed (license)
|
||||
'vendors/bootstrap/js/bootstrap.min.js', // fixed
|
||||
'dev/prototype-date.js',
|
||||
'dev/prototype-function.js',
|
||||
'node_modules/knockout/build/output/knockout-latest.js',
|
||||
'node_modules/knockout-sortable/build/knockout-sortable.min.js ',
|
||||
'node_modules/simplestatemanager/dist/ssm.min.js',
|
||||
|
|
Loading…
Reference in a new issue