mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-08-29 20:19:22 +03:00
Converted *Ajax into *Fetch (because we use the Fetch API, not jQuery.ajax)
This commit is contained in:
parent
bb4d66d6d2
commit
29cf711a6a
52 changed files with 399 additions and 540 deletions
|
|
@ -1,216 +0,0 @@
|
|||
import { TOKEN_ERROR_LIMIT, AJAX_ERROR_LIMIT, DEFAULT_AJAX_TIMEOUT } from 'Common/Consts';
|
||||
import { StorageResultType, Notification } from 'Common/Enums';
|
||||
import { pInt, pString } from 'Common/Utils';
|
||||
import { data as GlobalsData } from 'Common/Globals';
|
||||
import { ajax } from 'Common/Links';
|
||||
|
||||
|
||||
class AbstractAjaxRemote {
|
||||
constructor() {
|
||||
this.oRequests = {};
|
||||
}
|
||||
|
||||
abort(sAction, bClearOnly) {
|
||||
if (this.oRequests[sAction]) {
|
||||
if (!bClearOnly && this.oRequests[sAction].abort) {
|
||||
// this.oRequests[sAction].__aborted = true;
|
||||
this.oRequests[sAction].abort();
|
||||
}
|
||||
|
||||
this.oRequests[sAction] = null;
|
||||
delete this.oRequests[sAction];
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {?Function} fCallback
|
||||
* @param {string} sRequestAction
|
||||
* @param {string} sType
|
||||
* @param {?AjaxJsonDefaultResponse} oData
|
||||
* @param {boolean} bCached
|
||||
* @param {*=} oRequestParameters
|
||||
*/
|
||||
defaultResponse(fCallback, sRequestAction, sType, oData, bCached, oRequestParameters) {
|
||||
const fCall = () => {
|
||||
if (StorageResultType.Success !== sType && GlobalsData.bUnload) {
|
||||
sType = StorageResultType.Unload;
|
||||
}
|
||||
|
||||
if (StorageResultType.Success === sType && oData && !oData.Result) {
|
||||
const err = oData ? oData.ErrorCode : null;
|
||||
if (
|
||||
oData && [
|
||||
Notification.AuthError,
|
||||
Notification.AccessError,
|
||||
Notification.ConnectionError,
|
||||
Notification.DomainNotAllowed,
|
||||
Notification.AccountNotAllowed,
|
||||
Notification.MailServerError,
|
||||
Notification.UnknownNotification,
|
||||
Notification.UnknownError
|
||||
].includes(err)
|
||||
) {
|
||||
++GlobalsData.iAjaxErrorCount;
|
||||
}
|
||||
|
||||
if (oData && Notification.InvalidToken === err) {
|
||||
++GlobalsData.iTokenErrorCount;
|
||||
}
|
||||
|
||||
if (TOKEN_ERROR_LIMIT < GlobalsData.iTokenErrorCount) {
|
||||
rl.logoutReload();
|
||||
}
|
||||
|
||||
if (oData.ClearAuth || oData.Logout || AJAX_ERROR_LIMIT < GlobalsData.iAjaxErrorCount) {
|
||||
if (GlobalsData.__APP__) {
|
||||
rl.hash.clear();
|
||||
|
||||
if (!oData.ClearAuth) {
|
||||
rl.logoutReload();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (StorageResultType.Success === sType && oData && oData.Result) {
|
||||
GlobalsData.iAjaxErrorCount = 0;
|
||||
GlobalsData.iTokenErrorCount = 0;
|
||||
}
|
||||
|
||||
if (fCallback) {
|
||||
fCallback(
|
||||
sType,
|
||||
StorageResultType.Success === sType ? oData : null,
|
||||
bCached,
|
||||
sRequestAction,
|
||||
oRequestParameters
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
switch (sType) {
|
||||
case 'success':
|
||||
sType = StorageResultType.Success;
|
||||
break;
|
||||
case 'abort':
|
||||
sType = StorageResultType.Abort;
|
||||
break;
|
||||
default:
|
||||
sType = StorageResultType.Error;
|
||||
break;
|
||||
}
|
||||
|
||||
if (StorageResultType.Error === sType) {
|
||||
setTimeout(fCall, 300);
|
||||
} else {
|
||||
fCall();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {?Function} fResultCallback
|
||||
* @param {Object} oParameters
|
||||
* @param {?number=} iTimeOut = 20000
|
||||
* @param {string=} sGetAdd = ''
|
||||
* @param {Array=} aAbortActions = []
|
||||
*/
|
||||
ajaxRequest(fResultCallback, params, iTimeOut = 20000, sGetAdd = '', abortActions = []) {
|
||||
params = params || {};
|
||||
const start = Date.now(),
|
||||
action = params.Action || '';
|
||||
|
||||
if (action && abortActions) {
|
||||
abortActions.forEach(actionToAbort => this.abort(actionToAbort));
|
||||
}
|
||||
|
||||
let init = {};
|
||||
|
||||
if (window.AbortController) {
|
||||
this.abort(action);
|
||||
const controller = new AbortController();
|
||||
if (iTimeOut) {
|
||||
setTimeout(() => controller.abort(), iTimeOut);
|
||||
}
|
||||
init.signal = controller.signal;
|
||||
this.oRequests[action] = controller;
|
||||
}
|
||||
|
||||
return rl.fetchJSON(ajax(sGetAdd), init, iTimeOut, sGetAdd ? null : params)
|
||||
.then(oData => {
|
||||
let cached = false;
|
||||
if (oData && oData.Time) {
|
||||
cached = pInt(oData.Time) > Date.now() - start;
|
||||
}
|
||||
|
||||
if (oData && oData.UpdateToken) {
|
||||
rl.hash.set();
|
||||
rl.settings.set('AuthAccountHash', oData.UpdateToken);
|
||||
}
|
||||
|
||||
let sType = 'success';
|
||||
if (action && this.oRequests[action]) {
|
||||
if (this.oRequests[action].__aborted) {
|
||||
sType = 'abort';
|
||||
}
|
||||
|
||||
this.oRequests[action] = null;
|
||||
}
|
||||
|
||||
this.defaultResponse(fResultCallback, action, sType, oData, cached, params);
|
||||
}).catch(err => {
|
||||
if (err.name == 'AbortError') { // handle abort()
|
||||
return Promise.reject(Notification.AjaxAbort);
|
||||
}
|
||||
return Promise.reject(err);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {?Function} fCallback
|
||||
* @param {string} sAction
|
||||
* @param {Object=} oParameters
|
||||
* @param {?number=} iTimeout
|
||||
* @param {string=} sGetAdd = ''
|
||||
* @param {Array=} aAbortActions = []
|
||||
*/
|
||||
defaultRequest(fCallback, sAction, oParameters, iTimeout, sGetAdd, aAbortActions) {
|
||||
oParameters = oParameters || {};
|
||||
oParameters.Action = sAction;
|
||||
|
||||
sGetAdd = pString(sGetAdd);
|
||||
|
||||
return this.ajaxRequest(
|
||||
fCallback,
|
||||
oParameters,
|
||||
undefined === iTimeout ? DEFAULT_AJAX_TIMEOUT : pInt(iTimeout),
|
||||
sGetAdd,
|
||||
aAbortActions
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {?Function} fCallback
|
||||
*/
|
||||
noop(fCallback) {
|
||||
this.defaultRequest(fCallback, 'Noop');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {?Function} fCallback
|
||||
*/
|
||||
getPublicKey(fCallback) {
|
||||
this.defaultRequest(fCallback, 'GetPublicKey');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {?Function} fCallback
|
||||
* @param {string} sVersion
|
||||
*/
|
||||
jsVersion(fCallback, sVersion) {
|
||||
this.defaultRequest(fCallback, 'Version', {
|
||||
'Version': sVersion
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export { AbstractAjaxRemote, AbstractAjaxRemote as default };
|
||||
282
dev/Remote/AbstractFetch.js
Normal file
282
dev/Remote/AbstractFetch.js
Normal file
|
|
@ -0,0 +1,282 @@
|
|||
import { TOKEN_ERROR_LIMIT, AJAX_ERROR_LIMIT, DEFAULT_AJAX_TIMEOUT } from 'Common/Consts';
|
||||
import { StorageResultType, Notification } from 'Common/Enums';
|
||||
import { pInt, pString } from 'Common/Utils';
|
||||
import { serverRequest } from 'Common/Links';
|
||||
|
||||
let iAjaxErrorCount = 0,
|
||||
iTokenErrorCount = 0,
|
||||
bUnload = false;
|
||||
|
||||
const getURL = (add = '') => serverRequest('Ajax') + add,
|
||||
|
||||
updateToken = data => {
|
||||
if (data.UpdateToken) {
|
||||
rl.hash.set();
|
||||
rl.settings.set('AuthAccountHash', data.UpdateToken);
|
||||
}
|
||||
},
|
||||
|
||||
checkResponseError = data => {
|
||||
const err = data ? data.ErrorCode : null;
|
||||
if ([
|
||||
Notification.AuthError,
|
||||
Notification.AccessError,
|
||||
Notification.ConnectionError,
|
||||
Notification.DomainNotAllowed,
|
||||
Notification.AccountNotAllowed,
|
||||
Notification.MailServerError,
|
||||
Notification.UnknownNotification,
|
||||
Notification.UnknownError
|
||||
].includes(err)
|
||||
) {
|
||||
++iAjaxErrorCount;
|
||||
}
|
||||
|
||||
if (Notification.InvalidToken === err) {
|
||||
++iTokenErrorCount;
|
||||
}
|
||||
|
||||
if (TOKEN_ERROR_LIMIT < iTokenErrorCount) {
|
||||
rl.logoutReload();
|
||||
}
|
||||
|
||||
if (window.rl && (data.ClearAuth || data.Logout || AJAX_ERROR_LIMIT < iAjaxErrorCount)) {
|
||||
rl.hash.clear();
|
||||
|
||||
if (!data.ClearAuth) {
|
||||
rl.logoutReload();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
oRequests = {};
|
||||
|
||||
addEventListener('unload', () => bUnload = true);
|
||||
|
||||
class AbstractFetchRemote
|
||||
{
|
||||
abort(sAction, bClearOnly) {
|
||||
if (oRequests[sAction]) {
|
||||
if (!bClearOnly && oRequests[sAction].abort) {
|
||||
// oRequests[sAction].__aborted = true;
|
||||
oRequests[sAction].abort();
|
||||
}
|
||||
|
||||
oRequests[sAction] = null;
|
||||
delete oRequests[sAction];
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {?Function} fResultCallback
|
||||
* @param {Object} oParameters
|
||||
* @param {?number=} iTimeOut = 20000
|
||||
* @param {string=} sGetAdd = ''
|
||||
* @param {Array=} aAbortActions = []
|
||||
*/
|
||||
ajaxRequest(fResultCallback, params, iTimeOut = 20000, sGetAdd = '', abortActions = []) {
|
||||
params = params || {};
|
||||
const start = Date.now(),
|
||||
action = params.Action || '';
|
||||
|
||||
if (action && abortActions) {
|
||||
abortActions.forEach(actionToAbort => this.abort(actionToAbort));
|
||||
}
|
||||
|
||||
return rl.fetchJSON(getURL(sGetAdd), {
|
||||
signal: this.createAbort(action, iTimeOut)
|
||||
}, iTimeOut, sGetAdd ? null : params
|
||||
).then(data => {
|
||||
let cached = false;
|
||||
if (data) {
|
||||
if (data.Time) {
|
||||
cached = pInt(data.Time) > Date.now() - start;
|
||||
}
|
||||
|
||||
updateToken(data);
|
||||
}
|
||||
|
||||
let sType = 'success';
|
||||
if (action && oRequests[action]) {
|
||||
if (oRequests[action].__aborted) {
|
||||
sType = 'abort';
|
||||
}
|
||||
this.abort(action, true);
|
||||
}
|
||||
|
||||
const fCall = () => {
|
||||
if (StorageResultType.Success !== sType && bUnload) {
|
||||
sType = StorageResultType.Unload;
|
||||
}
|
||||
|
||||
if (StorageResultType.Success === sType && data && !data.Result) {
|
||||
checkResponseError(data);
|
||||
} else if (StorageResultType.Success === sType && data && data.Result) {
|
||||
iAjaxErrorCount = iTokenErrorCount = 0;
|
||||
}
|
||||
|
||||
if (fResultCallback) {
|
||||
fResultCallback(
|
||||
sType,
|
||||
StorageResultType.Success === sType ? data : null,
|
||||
cached,
|
||||
action,
|
||||
params
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
switch (sType) {
|
||||
case 'success':
|
||||
sType = StorageResultType.Success;
|
||||
break;
|
||||
case 'abort':
|
||||
sType = StorageResultType.Abort;
|
||||
break;
|
||||
default:
|
||||
sType = StorageResultType.Error;
|
||||
break;
|
||||
}
|
||||
|
||||
if (StorageResultType.Error === sType) {
|
||||
setTimeout(fCall, 300);
|
||||
} else {
|
||||
fCall();
|
||||
}
|
||||
|
||||
}).catch(err => {
|
||||
if (err.name == 'AbortError') { // handle abort()
|
||||
err = Notification.AjaxAbort;
|
||||
}
|
||||
return Promise.reject(err);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {?Function} fCallback
|
||||
* @param {string} sAction
|
||||
* @param {Object=} oParameters
|
||||
* @param {?number=} iTimeout
|
||||
* @param {string=} sGetAdd = ''
|
||||
* @param {Array=} aAbortActions = []
|
||||
*/
|
||||
defaultRequest(fCallback, sAction, oParameters, iTimeout, sGetAdd, aAbortActions) {
|
||||
oParameters = oParameters || {};
|
||||
oParameters.Action = sAction;
|
||||
|
||||
return this.ajaxRequest(
|
||||
fCallback,
|
||||
oParameters,
|
||||
undefined === iTimeout ? DEFAULT_AJAX_TIMEOUT : pInt(iTimeout),
|
||||
pString(sGetAdd),
|
||||
aAbortActions
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {?Function} fCallback
|
||||
*/
|
||||
noop(fCallback) {
|
||||
this.defaultRequest(fCallback, 'Noop');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {?Function} fCallback
|
||||
*/
|
||||
getPublicKey(fCallback) {
|
||||
this.defaultRequest(fCallback, 'GetPublicKey');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {?Function} fCallback
|
||||
* @param {string} sVersion
|
||||
*/
|
||||
jsVersion(fCallback, sVersion) {
|
||||
this.defaultRequest(fCallback, 'Version', {
|
||||
'Version': sVersion
|
||||
});
|
||||
}
|
||||
|
||||
createAbort(action, timeout) {
|
||||
if (window.AbortController) {
|
||||
this.abort(action);
|
||||
const controller = new AbortController();
|
||||
if (timeout) {
|
||||
setTimeout(() => controller.abort(), timeout);
|
||||
}
|
||||
oRequests[action] = controller;
|
||||
return controller.signal;
|
||||
}
|
||||
}
|
||||
|
||||
fastResolve(mData) {
|
||||
return Promise.resolve(mData);
|
||||
}
|
||||
|
||||
setTrigger(trigger, value) {
|
||||
if (trigger) {
|
||||
value = !!value;
|
||||
(Array.isArray(trigger) ? trigger : [trigger]).forEach((fTrigger) => {
|
||||
if (fTrigger) {
|
||||
fTrigger(value);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
postRequest(action, fTrigger, params, timeOut) {
|
||||
params = params || {};
|
||||
params.Action = action;
|
||||
|
||||
this.setTrigger(fTrigger, true);
|
||||
|
||||
return rl.fetchJSON(getURL(), {
|
||||
signal: this.createAbort(action, pInt(timeOut, DEFAULT_AJAX_TIMEOUT))
|
||||
}, pInt(timeOut, DEFAULT_AJAX_TIMEOUT), params
|
||||
).then(data => {
|
||||
this.abort(action, true);
|
||||
|
||||
if (!data) {
|
||||
return Promise.reject(Notification.AjaxParse);
|
||||
}
|
||||
|
||||
updateToken(data);
|
||||
/*
|
||||
let isCached = false, type = '';
|
||||
if (data && data.Time) {
|
||||
isCached = pInt(data.Time) > microtime() - start;
|
||||
}
|
||||
// backward capability
|
||||
switch (true) {
|
||||
case 'success' === textStatus && data && data.Result && action === data.Action:
|
||||
type = StorageResultType.Success;
|
||||
break;
|
||||
case 'abort' === textStatus && (!data || !data.__aborted__):
|
||||
type = StorageResultType.Abort;
|
||||
break;
|
||||
default:
|
||||
type = StorageResultType.Error;
|
||||
break;
|
||||
}
|
||||
*/
|
||||
this.setTrigger(fTrigger, false);
|
||||
|
||||
if (!data.Result || action !== data.Action) {
|
||||
checkResponseError(data);
|
||||
const err = data ? data.ErrorCode : null;
|
||||
return Promise.reject(err || Notification.AjaxFalse);
|
||||
}
|
||||
|
||||
return data;
|
||||
}).catch(err => {
|
||||
if (err.name == 'AbortError') { // handle abort()
|
||||
return Promise.reject(Notification.AjaxAbort);
|
||||
}
|
||||
return Promise.reject(err);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export { AbstractFetchRemote, AbstractFetchRemote as default };
|
||||
|
|
@ -1,12 +1,6 @@
|
|||
import { AbstractAjaxRemote } from 'Remote/AbstractAjax';
|
||||
|
||||
class RemoteAdminAjax extends AbstractAjaxRemote {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.oRequests = {};
|
||||
}
|
||||
import { AbstractFetchRemote } from 'Remote/AbstractFetch';
|
||||
|
||||
class RemoteAdminFetch extends AbstractFetchRemote {
|
||||
/**
|
||||
* @param {?Function} fCallback
|
||||
* @param {string} sLogin
|
||||
|
|
@ -271,4 +265,4 @@ class RemoteAdminAjax extends AbstractAjaxRemote {
|
|||
}
|
||||
}
|
||||
|
||||
export default new RemoteAdminAjax();
|
||||
export default new RemoteAdminFetch();
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import { pString, pInt } from 'Common/Utils';
|
||||
import PromisesPopulator from 'Promises/User/Populator';
|
||||
|
||||
import {
|
||||
CONTACTS_SYNC_AJAX_TIMEOUT,
|
||||
|
|
@ -23,7 +24,7 @@ import SettingsStore from 'Stores/User/Settings';
|
|||
|
||||
import { getApp } from 'Helper/Apps/User';
|
||||
|
||||
import { AbstractAjaxRemote } from 'Remote/AbstractAjax';
|
||||
import { AbstractFetchRemote } from 'Remote/AbstractFetch';
|
||||
|
||||
//const toUTF8 = window.TextEncoder
|
||||
// ? text => String.fromCharCode(...new TextEncoder().encode(text))
|
||||
|
|
@ -33,12 +34,7 @@ const urlsafeArray = array => btoa(unescape(encodeURIComponent(array.join('\x00'
|
|||
.replace('/', '_')
|
||||
.replace('=', '');
|
||||
|
||||
class RemoteUserAjax extends AbstractAjaxRemote {
|
||||
constructor() {
|
||||
super();
|
||||
this.oRequests = {};
|
||||
}
|
||||
|
||||
class RemoteUserFetch extends AbstractFetchRemote {
|
||||
/**
|
||||
* @param {?Function} fCallback
|
||||
*/
|
||||
|
|
@ -775,6 +771,50 @@ class RemoteUserAjax extends AbstractAjaxRemote {
|
|||
clearUserBackground(fCallback) {
|
||||
this.defaultRequest(fCallback, 'ClearUserBackground');
|
||||
}
|
||||
|
||||
foldersReload(fTrigger) {
|
||||
return this.abort('Folders')
|
||||
.postRequest('Folders', fTrigger)
|
||||
.then((data) => {
|
||||
PromisesPopulator.foldersList(data.Result);
|
||||
PromisesPopulator.foldersAdditionalParameters(data.Result);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
foldersReloadWithTimeout(fTrigger) {
|
||||
this.setTrigger(fTrigger, true);
|
||||
|
||||
clearTimeout(this.foldersTimeout);
|
||||
this.foldersTimeout = setTimeout(() => this.foldersReload(fTrigger), 500);
|
||||
}
|
||||
|
||||
folderDelete(sFolderFullNameRaw, fTrigger) {
|
||||
return this.postRequest('FolderDelete', fTrigger, {
|
||||
'Folder': sFolderFullNameRaw
|
||||
});
|
||||
}
|
||||
|
||||
folderCreate(sNewFolderName, sParentName, fTrigger) {
|
||||
return this.postRequest('FolderCreate', fTrigger, {
|
||||
'Folder': sNewFolderName,
|
||||
'Parent': sParentName
|
||||
});
|
||||
}
|
||||
|
||||
folderRename(sPrevFolderFullNameRaw, sNewFolderName, fTrigger) {
|
||||
return this.postRequest('FolderRename', fTrigger, {
|
||||
'Folder': sPrevFolderFullNameRaw,
|
||||
'NewFolderName': sNewFolderName
|
||||
});
|
||||
}
|
||||
|
||||
attachmentsActions(sAction, aHashes, fTrigger) {
|
||||
return this.postRequest('AttachmentsActions', fTrigger, {
|
||||
'Do': sAction,
|
||||
'Hashes': aHashes
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new RemoteUserAjax();
|
||||
export default new RemoteUserFetch();
|
||||
Loading…
Add table
Add a link
Reference in a new issue