* 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>
150 lines
4.4 KiB
TypeScript
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,
|
|
};
|
|
}
|
|
}
|
|
|