mattermost-mobile/app/mm-redux/actions/helpers.ts
Miguel Alatzar 9a0bce5b6d [MM-23698] [MM-19559] Remove redux-offline and updated redux-persist (#4120)
* Remove redux-offline and configure redux-persist

* Fix typo

* Fix configure store

* Upgrade to redux-persist 6.0.0

* Add migration from redux-persist v4 to v6

* Replace AsyncStorage with MMKVStorage to boost storage speed

* Mock RNFastStorage

* Fix reactions test

* Fix clearing the store on logout

* Remove the need for LOGOUT_SUCCESS

* No need to pass persistConfig to middlewares()

* Remove unused imports

* Export connection

Accidentally removed this export.

* Add batch action name

Co-Authored-By: Elias Nahum <nahumhbl@gmail.com>

* Add batch action name

Co-Authored-By: Elias Nahum <nahumhbl@gmail.com>

* Add batch action name

Co-Authored-By: Elias Nahum <nahumhbl@gmail.com>

* Add batch action name

Co-Authored-By: Elias Nahum <nahumhbl@gmail.com>

* Fix delete post

* Fix leave channel

Co-authored-by: Elias Nahum <nahumhbl@gmail.com>
2020-04-17 22:30:27 -07:00

150 lines
4.4 KiB
TypeScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {logout} from '@actions/views/user';
import {Client4Error} from '@mm-redux/types/client4';
import {batchActions, Action, ActionFunc, GenericAction, DispatchFunc, GetStateFunc} from '@mm-redux/types/actions';
import {logError} from './errors';
type ActionType = string;
const HTTP_UNAUTHORIZED = 401;
export function forceLogoutIfNecessary(err: Client4Error, dispatch: DispatchFunc, getState: GetStateFunc) {
const {currentUserId} = getState().entities.users;
if ('status_code' in err && err.status_code === HTTP_UNAUTHORIZED && err.url && err.url.indexOf('/login') === -1 && currentUserId) {
dispatch(logout(false));
}
}
function dispatcher(type: ActionType, data: any, dispatch: DispatchFunc, getState: GetStateFunc) {
if (type.indexOf('SUCCESS') === -1) { // we don't want to pass the data for the request types
dispatch(requestSuccess(type, data));
} else {
dispatch(requestData(type));
}
}
export function requestData(type: ActionType): GenericAction {
return {
type,
data: null,
};
}
export function requestSuccess(type: ActionType, data: any) {
return {
type,
data,
};
}
export function requestFailure(type: ActionType, error: Client4Error): any {
return {
type,
error,
};
}
/**
* Returns an ActionFunc which calls a specfied (client) function and
* dispatches the specifed actions on request, success or failure.
*
* @export
* @param {Object} obj an object for destructirung required properties
* @param {() => Promise<mixed>} obj.clientFunc clientFunc to execute
* @param {ActionType} obj.onRequest ActionType to dispatch on request
* @param {(ActionType | Array<ActionType>)} obj.onSuccess ActionType to dispatch on success
* @param {ActionType} obj.onFailure ActionType to dispatch on failure
* @param {...Array<any>} obj.params
* @returns {ActionFunc} ActionFunc
*/
export function bindClientFunc({
clientFunc,
onRequest,
onSuccess,
onFailure,
params = [],
}: {
clientFunc: (...args: any[]) => Promise<any>;
onRequest?: ActionType;
onSuccess?: ActionType | Array<ActionType>;
onFailure?: ActionType;
params?: Array<any>;
}): ActionFunc {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => {
if (onRequest) {
dispatch(requestData(onRequest));
}
let data: any = null;
try {
data = await clientFunc(...params);
} catch (error) {
forceLogoutIfNecessary(error, dispatch, getState);
const actions: Action[] = [logError(error)];
if (onFailure) {
actions.push(requestFailure(onFailure, error));
}
dispatch(batchActions(actions));
return {error};
}
if (Array.isArray(onSuccess)) {
onSuccess.forEach((s) => {
dispatcher(s, data, dispatch, getState);
});
} else if (onSuccess) {
dispatcher(onSuccess, data, dispatch, getState);
}
return {data};
};
}
// Debounce function based on underscores modified to use es6 and a cb
export function debounce(func: (...args: any) => unknown, wait: number, immediate: boolean, cb: () => unknown) {
let timeout: NodeJS.Timeout|null;
return function fx(...args: Array<any>) {
const runLater = () => {
timeout = null;
if (!immediate) {
Reflect.apply(func, this, args);
if (cb) {
cb();
}
}
};
const callNow = immediate && !timeout;
if (timeout) {
clearTimeout(timeout);
}
timeout = setTimeout(runLater, wait);
if (callNow) {
Reflect.apply(func, this, args);
if (cb) {
cb();
}
}
};
}
export class FormattedError extends Error {
intl: {
id: string;
defaultMessage: string;
values: any;
};
constructor(id: string, defaultMessage: string, values: any = {}) {
super(defaultMessage);
this.intl = {
id,
defaultMessage,
values,
};
}
}