Compare commits
26 Commits
develop
...
chore/migr
Author | SHA1 | Date |
---|---|---|
GleidsonDaniel | 6bc0e82fdc | |
GleidsonDaniel | 1db676f424 | |
GleidsonDaniel | ba2931665b | |
GleidsonDaniel | 701361a686 | |
GleidsonDaniel | 16e04c7232 | |
GleidsonDaniel | bc92a4f29d | |
GleidsonDaniel | 0cf9765f86 | |
GleidsonDaniel | 48e4640bee | |
GleidsonDaniel | c471195d8c | |
GleidsonDaniel | 928fac17de | |
GleidsonDaniel | bad5643a4d | |
GleidsonDaniel | f0977ddb22 | |
GleidsonDaniel | d12b28b5f5 | |
GleidsonDaniel | ef0d2bf195 | |
GleidsonDaniel | ff0925cc96 | |
GleidsonDaniel | b56f6048d4 | |
GleidsonDaniel | b5bda757bc | |
GleidsonDaniel | b80c0635d6 | |
GleidsonDaniel | 69f27438b2 | |
GleidsonDaniel | f169f6e0a7 | |
GleidsonDaniel | dc83f76843 | |
GleidsonDaniel | 010676aa85 | |
GleidsonDaniel | 003f9fca68 | |
GleidsonDaniel | 9d7450b300 | |
GleidsonDaniel | 34e6ece871 | |
GleidsonDaniel | 3b97c34959 |
|
@ -17,14 +17,15 @@ module.exports = {
|
||||||
legacyDecorators: true
|
legacyDecorators: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
plugins: ['react', 'jsx-a11y', 'import', 'react-native', '@babel'],
|
plugins: ['react', 'jsx-a11y', 'import', 'react-native', '@babel', 'jest'],
|
||||||
env: {
|
env: {
|
||||||
browser: true,
|
browser: true,
|
||||||
commonjs: true,
|
commonjs: true,
|
||||||
es6: true,
|
es6: true,
|
||||||
node: true,
|
node: true,
|
||||||
jquery: true,
|
jquery: true,
|
||||||
mocha: true
|
mocha: true,
|
||||||
|
'jest/globals': true
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
'import/extensions': [
|
'import/extensions': [
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { connect } from 'react-redux';
|
||||||
import { SetUsernameStackParamList, StackParamList } from './navigationTypes';
|
import { SetUsernameStackParamList, StackParamList } from './navigationTypes';
|
||||||
import Navigation from './lib/Navigation';
|
import Navigation from './lib/Navigation';
|
||||||
import { defaultHeader, getActiveRouteName, navigationTheme } from './utils/navigation';
|
import { defaultHeader, getActiveRouteName, navigationTheme } from './utils/navigation';
|
||||||
import { ROOT_INSIDE, ROOT_LOADING, ROOT_OUTSIDE, ROOT_SET_USERNAME } from './actions/app';
|
import { RootEnum } from './definitions';
|
||||||
// Stacks
|
// Stacks
|
||||||
import AuthLoadingView from './views/AuthLoadingView';
|
import AuthLoadingView from './views/AuthLoadingView';
|
||||||
// SetUsername Stack
|
// SetUsername Stack
|
||||||
|
@ -56,13 +56,13 @@ const App = React.memo(({ root, isMasterDetail }: { root: string; isMasterDetail
|
||||||
}}>
|
}}>
|
||||||
<Stack.Navigator screenOptions={{ headerShown: false, animationEnabled: false }}>
|
<Stack.Navigator screenOptions={{ headerShown: false, animationEnabled: false }}>
|
||||||
<>
|
<>
|
||||||
{root === ROOT_LOADING ? <Stack.Screen name='AuthLoading' component={AuthLoadingView} /> : null}
|
{root === RootEnum.ROOT_LOADING ? <Stack.Screen name='AuthLoading' component={AuthLoadingView} /> : null}
|
||||||
{root === ROOT_OUTSIDE ? <Stack.Screen name='OutsideStack' component={OutsideStack} /> : null}
|
{root === RootEnum.ROOT_OUTSIDE ? <Stack.Screen name='OutsideStack' component={OutsideStack} /> : null}
|
||||||
{root === ROOT_INSIDE && isMasterDetail ? (
|
{root === RootEnum.ROOT_INSIDE && isMasterDetail ? (
|
||||||
<Stack.Screen name='MasterDetailStack' component={MasterDetailStack} />
|
<Stack.Screen name='MasterDetailStack' component={MasterDetailStack} />
|
||||||
) : null}
|
) : null}
|
||||||
{root === ROOT_INSIDE && !isMasterDetail ? <Stack.Screen name='InsideStack' component={InsideStack} /> : null}
|
{root === RootEnum.ROOT_INSIDE && !isMasterDetail ? <Stack.Screen name='InsideStack' component={InsideStack} /> : null}
|
||||||
{root === ROOT_SET_USERNAME ? <Stack.Screen name='SetUsernameStack' component={SetUsernameStack} /> : null}
|
{root === RootEnum.ROOT_SET_USERNAME ? <Stack.Screen name='SetUsernameStack' component={SetUsernameStack} /> : null}
|
||||||
</>
|
</>
|
||||||
</Stack.Navigator>
|
</Stack.Navigator>
|
||||||
</NavigationContainer>
|
</NavigationContainer>
|
||||||
|
|
|
@ -2,8 +2,8 @@ const REQUEST = 'REQUEST';
|
||||||
const SUCCESS = 'SUCCESS';
|
const SUCCESS = 'SUCCESS';
|
||||||
const FAILURE = 'FAILURE';
|
const FAILURE = 'FAILURE';
|
||||||
const defaultTypes = [REQUEST, SUCCESS, FAILURE];
|
const defaultTypes = [REQUEST, SUCCESS, FAILURE];
|
||||||
function createRequestTypes(base, types = defaultTypes) {
|
function createRequestTypes(base = {}, types = defaultTypes): Record<string, string> {
|
||||||
const res = {};
|
const res: Record<string, string> = {};
|
||||||
types.forEach(type => (res[type] = `${base}_${type}`));
|
types.forEach(type => (res[type] = `${base}_${type}`));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
|
@ -1,8 +0,0 @@
|
||||||
import { SET_ACTIVE_USERS } from './actionsTypes';
|
|
||||||
|
|
||||||
export function setActiveUsers(activeUsers) {
|
|
||||||
return {
|
|
||||||
type: SET_ACTIVE_USERS,
|
|
||||||
activeUsers
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { Action } from 'redux';
|
||||||
|
|
||||||
|
import { IActiveUsers } from '../reducers/activeUsers';
|
||||||
|
import { SET_ACTIVE_USERS } from './actionsTypes';
|
||||||
|
|
||||||
|
interface ISetActiveUsers extends Action {
|
||||||
|
activeUsers: IActiveUsers;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TActionActiveUsers = ISetActiveUsers;
|
||||||
|
|
||||||
|
export const setActiveUsers = (activeUsers: IActiveUsers): ISetActiveUsers => ({
|
||||||
|
type: SET_ACTIVE_USERS,
|
||||||
|
activeUsers
|
||||||
|
});
|
|
@ -1,39 +0,0 @@
|
||||||
import { APP } from './actionsTypes';
|
|
||||||
|
|
||||||
export const ROOT_OUTSIDE = 'outside';
|
|
||||||
export const ROOT_INSIDE = 'inside';
|
|
||||||
export const ROOT_LOADING = 'loading';
|
|
||||||
export const ROOT_SET_USERNAME = 'setUsername';
|
|
||||||
|
|
||||||
export function appStart({ root, ...args }) {
|
|
||||||
return {
|
|
||||||
type: APP.START,
|
|
||||||
root,
|
|
||||||
...args
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function appReady() {
|
|
||||||
return {
|
|
||||||
type: APP.READY
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function appInit() {
|
|
||||||
return {
|
|
||||||
type: APP.INIT
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function appInitLocalSettings() {
|
|
||||||
return {
|
|
||||||
type: APP.INIT_LOCAL_SETTINGS
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setMasterDetail(isMasterDetail) {
|
|
||||||
return {
|
|
||||||
type: APP.SET_MASTER_DETAIL,
|
|
||||||
isMasterDetail
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
import { Action } from 'redux';
|
||||||
|
|
||||||
|
import { RootEnum } from '../definitions';
|
||||||
|
import { APP } from './actionsTypes';
|
||||||
|
|
||||||
|
interface IAppStart extends Action {
|
||||||
|
root: RootEnum;
|
||||||
|
text?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ISetMasterDetail extends Action {
|
||||||
|
isMasterDetail: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TActionApp = IAppStart & ISetMasterDetail;
|
||||||
|
|
||||||
|
export function appStart({ root, ...args }: { root: RootEnum }): IAppStart {
|
||||||
|
return {
|
||||||
|
type: APP.START,
|
||||||
|
root,
|
||||||
|
...args
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function appReady(): Action {
|
||||||
|
return {
|
||||||
|
type: APP.READY
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function appInit(): Action {
|
||||||
|
return {
|
||||||
|
type: APP.INIT
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function appInitLocalSettings(): Action {
|
||||||
|
return {
|
||||||
|
type: APP.INIT_LOCAL_SETTINGS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setMasterDetail(isMasterDetail: boolean): ISetMasterDetail {
|
||||||
|
return {
|
||||||
|
type: APP.SET_MASTER_DETAIL,
|
||||||
|
isMasterDetail
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,20 +0,0 @@
|
||||||
import * as types from './actionsTypes';
|
|
||||||
|
|
||||||
export function connectRequest() {
|
|
||||||
return {
|
|
||||||
type: types.METEOR.REQUEST
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function connectSuccess() {
|
|
||||||
return {
|
|
||||||
type: types.METEOR.SUCCESS
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function disconnect(err) {
|
|
||||||
return {
|
|
||||||
type: types.METEOR.DISCONNECT,
|
|
||||||
err
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { Action } from 'redux';
|
||||||
|
|
||||||
|
import * as types from './actionsTypes';
|
||||||
|
|
||||||
|
export function connectRequest(): Action {
|
||||||
|
return {
|
||||||
|
type: types.METEOR.REQUEST
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function connectSuccess(): Action {
|
||||||
|
return {
|
||||||
|
type: types.METEOR.SUCCESS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function disconnect(): Action {
|
||||||
|
return {
|
||||||
|
type: types.METEOR.DISCONNECT
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,28 +0,0 @@
|
||||||
import * as types from './actionsTypes';
|
|
||||||
|
|
||||||
export function addUser(user) {
|
|
||||||
return {
|
|
||||||
type: types.SELECTED_USERS.ADD_USER,
|
|
||||||
user
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function removeUser(user) {
|
|
||||||
return {
|
|
||||||
type: types.SELECTED_USERS.REMOVE_USER,
|
|
||||||
user
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function reset() {
|
|
||||||
return {
|
|
||||||
type: types.SELECTED_USERS.RESET
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setLoading(loading) {
|
|
||||||
return {
|
|
||||||
type: types.SELECTED_USERS.SET_LOADING,
|
|
||||||
loading
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
import { Action } from 'redux';
|
||||||
|
|
||||||
|
import { ISelectedUser } from '../reducers/selectedUsers';
|
||||||
|
import * as types from './actionsTypes';
|
||||||
|
|
||||||
|
type TUser = {
|
||||||
|
user: ISelectedUser;
|
||||||
|
};
|
||||||
|
|
||||||
|
type TAction = Action & TUser;
|
||||||
|
|
||||||
|
interface ISetLoading extends Action {
|
||||||
|
loading: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TActionSelectedUsers = TAction & ISetLoading;
|
||||||
|
|
||||||
|
export function addUser(user: ISelectedUser): TAction {
|
||||||
|
return {
|
||||||
|
type: types.SELECTED_USERS.ADD_USER,
|
||||||
|
user
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function removeUser(user: ISelectedUser): TAction {
|
||||||
|
return {
|
||||||
|
type: types.SELECTED_USERS.REMOVE_USER,
|
||||||
|
user
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function reset(): Action {
|
||||||
|
return {
|
||||||
|
type: types.SELECTED_USERS.RESET
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setLoading(loading: boolean): ISetLoading {
|
||||||
|
return {
|
||||||
|
type: types.SELECTED_USERS.SET_LOADING,
|
||||||
|
loading
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { RouteProp } from '@react-navigation/native';
|
||||||
|
import { StackNavigationProp } from '@react-navigation/stack';
|
||||||
|
import { Dispatch } from 'redux';
|
||||||
|
|
||||||
|
export interface IBaseScreen<T extends Record<string, object | undefined>, S extends string> {
|
||||||
|
navigation: StackNavigationProp<T, S>;
|
||||||
|
route: RouteProp<T, S>;
|
||||||
|
dispatch: Dispatch;
|
||||||
|
theme: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export * from './redux';
|
||||||
|
export * from './redux/TRootEnum';
|
|
@ -0,0 +1,6 @@
|
||||||
|
export enum RootEnum {
|
||||||
|
ROOT_OUTSIDE = 'outside',
|
||||||
|
ROOT_INSIDE = 'inside',
|
||||||
|
ROOT_LOADING = 'loading',
|
||||||
|
ROOT_SET_USERNAME = 'setUsername'
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
import { TActionSelectedUsers } from '../../actions/selectedUsers';
|
||||||
|
import { TActionActiveUsers } from '../../actions/activeUsers';
|
||||||
|
import { TActionApp } from '../../actions/app';
|
||||||
|
// REDUCERS
|
||||||
|
import { IActiveUsers } from '../../reducers/activeUsers';
|
||||||
|
import { ISelectedUsers } from '../../reducers/selectedUsers';
|
||||||
|
import { IApp } from '../../reducers/app';
|
||||||
|
import { IConnect } from '../../reducers/connect';
|
||||||
|
|
||||||
|
export interface IApplicationState {
|
||||||
|
settings: any;
|
||||||
|
login: any;
|
||||||
|
meteor: IConnect;
|
||||||
|
server: any;
|
||||||
|
selectedUsers: ISelectedUsers;
|
||||||
|
createChannel: any;
|
||||||
|
app: IApp;
|
||||||
|
room: any;
|
||||||
|
rooms: any;
|
||||||
|
sortPreferences: any;
|
||||||
|
share: any;
|
||||||
|
customEmojis: any;
|
||||||
|
activeUsers: IActiveUsers;
|
||||||
|
usersTyping: any;
|
||||||
|
inviteLinks: any;
|
||||||
|
createDiscussion: any;
|
||||||
|
inquiry: any;
|
||||||
|
enterpriseModules: any;
|
||||||
|
encryption: any;
|
||||||
|
permissions: any;
|
||||||
|
roles: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TApplicationActions = TActionActiveUsers & TActionSelectedUsers & TActionApp;
|
|
@ -1,15 +0,0 @@
|
||||||
import { SET_ACTIVE_USERS } from '../actions/actionsTypes';
|
|
||||||
|
|
||||||
const initialState = {};
|
|
||||||
|
|
||||||
export default function activeUsers(state = initialState, action) {
|
|
||||||
switch (action.type) {
|
|
||||||
case SET_ACTIVE_USERS:
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
...action.activeUsers
|
|
||||||
};
|
|
||||||
default:
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { setActiveUsers } from '../actions/activeUsers';
|
||||||
|
import { IActiveUsers, initialState } from './activeUsers';
|
||||||
|
import { mockedStore } from './mockedStore';
|
||||||
|
|
||||||
|
describe('test reducer', () => {
|
||||||
|
it('should return initial state', () => {
|
||||||
|
const state = mockedStore.getState().activeUsers;
|
||||||
|
expect(state).toEqual(initialState);
|
||||||
|
});
|
||||||
|
it('should return modified store after action', () => {
|
||||||
|
const activeUsers: IActiveUsers = { any: { status: 'online', statusText: 'any' } };
|
||||||
|
mockedStore.dispatch(setActiveUsers(activeUsers));
|
||||||
|
const state = mockedStore.getState().activeUsers;
|
||||||
|
expect(state).toEqual({ ...activeUsers });
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,26 @@
|
||||||
|
import { TApplicationActions } from '../definitions';
|
||||||
|
import { SET_ACTIVE_USERS } from '../actions/actionsTypes';
|
||||||
|
|
||||||
|
type TUserStatus = 'online' | 'offline';
|
||||||
|
export interface IActiveUser {
|
||||||
|
status: TUserStatus;
|
||||||
|
statusText?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IActiveUsers {
|
||||||
|
[key: string]: IActiveUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const initialState: IActiveUsers = {};
|
||||||
|
|
||||||
|
export default function activeUsers(state = initialState, action: TApplicationActions): IActiveUsers {
|
||||||
|
switch (action.type) {
|
||||||
|
case SET_ACTIVE_USERS:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
...action.activeUsers
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
import { appStart, appInit, setMasterDetail } from '../actions/app';
|
||||||
|
import { initialState } from './app';
|
||||||
|
import { mockedStore } from './mockedStore';
|
||||||
|
import { RootEnum } from '../definitions';
|
||||||
|
import { APP_STATE } from '../actions/actionsTypes';
|
||||||
|
|
||||||
|
describe('test reducer', () => {
|
||||||
|
it('should return initial state', () => {
|
||||||
|
const state = mockedStore.getState().app;
|
||||||
|
expect(state).toEqual(initialState);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return root state after dispatch appStart action', () => {
|
||||||
|
mockedStore.dispatch(appStart({ root: RootEnum.ROOT_INSIDE }));
|
||||||
|
const { root } = mockedStore.getState().app;
|
||||||
|
expect(root).toEqual(RootEnum.ROOT_INSIDE);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return ready state after dispatch appInit action', () => {
|
||||||
|
mockedStore.dispatch(appInit());
|
||||||
|
const { ready } = mockedStore.getState().app;
|
||||||
|
expect(ready).toEqual(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return ready state after dispatch setMasterDetail action', () => {
|
||||||
|
mockedStore.dispatch(setMasterDetail(false));
|
||||||
|
const { isMasterDetail } = mockedStore.getState().app;
|
||||||
|
expect(isMasterDetail).toEqual(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return correct state after app go to foreground', () => {
|
||||||
|
mockedStore.dispatch({ type: APP_STATE.FOREGROUND });
|
||||||
|
const { foreground, background } = mockedStore.getState().app;
|
||||||
|
expect(foreground).toEqual(true);
|
||||||
|
expect(background).toEqual(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return correct state after app go to background', () => {
|
||||||
|
mockedStore.dispatch({ type: APP_STATE.BACKGROUND });
|
||||||
|
const { foreground, background } = mockedStore.getState().app;
|
||||||
|
expect(foreground).toEqual(false);
|
||||||
|
expect(background).toEqual(true);
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,15 +1,26 @@
|
||||||
|
import { TActionApp } from '../actions/app';
|
||||||
|
import { RootEnum } from '../definitions';
|
||||||
import { APP, APP_STATE } from '../actions/actionsTypes';
|
import { APP, APP_STATE } from '../actions/actionsTypes';
|
||||||
|
|
||||||
const initialState = {
|
export interface IApp {
|
||||||
root: null,
|
root?: RootEnum;
|
||||||
|
isMasterDetail: boolean;
|
||||||
|
text?: string;
|
||||||
|
ready: boolean;
|
||||||
|
foreground: boolean;
|
||||||
|
background: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const initialState: IApp = {
|
||||||
|
root: undefined,
|
||||||
isMasterDetail: false,
|
isMasterDetail: false,
|
||||||
text: null,
|
text: undefined,
|
||||||
ready: false,
|
ready: false,
|
||||||
foreground: true,
|
foreground: true,
|
||||||
background: false
|
background: false
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function app(state = initialState, action) {
|
export default function app(state = initialState, action: TActionApp): IApp {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case APP_STATE.FOREGROUND:
|
case APP_STATE.FOREGROUND:
|
||||||
return {
|
return {
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { connectRequest, connectSuccess, disconnect } from '../actions/connect';
|
||||||
|
import { initialState } from './connect';
|
||||||
|
import { mockedStore } from './mockedStore';
|
||||||
|
|
||||||
|
describe('test reducer', () => {
|
||||||
|
it('should return initial state', () => {
|
||||||
|
const { meteor } = mockedStore.getState();
|
||||||
|
expect(meteor).toEqual(initialState);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return correct meteor state after dispatch connectRequest action', () => {
|
||||||
|
mockedStore.dispatch(connectRequest());
|
||||||
|
const { meteor } = mockedStore.getState();
|
||||||
|
expect(meteor).toEqual({ connecting: true, connected: false });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return correct meteor state after dispatch connectSuccess action', () => {
|
||||||
|
mockedStore.dispatch(connectSuccess());
|
||||||
|
const { meteor } = mockedStore.getState();
|
||||||
|
expect(meteor).toEqual({ connecting: false, connected: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return correct meteor state after dispatch disconnect action', () => {
|
||||||
|
mockedStore.dispatch(disconnect());
|
||||||
|
const { meteor } = mockedStore.getState();
|
||||||
|
expect(meteor).toEqual(initialState);
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,11 +1,18 @@
|
||||||
|
import { Action } from 'redux';
|
||||||
|
|
||||||
import { METEOR } from '../actions/actionsTypes';
|
import { METEOR } from '../actions/actionsTypes';
|
||||||
|
|
||||||
const initialState = {
|
export interface IConnect {
|
||||||
|
connecting: boolean;
|
||||||
|
connected: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const initialState: IConnect = {
|
||||||
connecting: false,
|
connecting: false,
|
||||||
connected: false
|
connected: false
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function connect(state = initialState, action) {
|
export default function connect(state = initialState, action: Action): IConnect {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case METEOR.REQUEST:
|
case METEOR.REQUEST:
|
||||||
return {
|
return {
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { applyMiddleware, compose, createStore } from 'redux';
|
||||||
|
import createSagaMiddleware from 'redux-saga';
|
||||||
|
|
||||||
|
import reducers from '.';
|
||||||
|
|
||||||
|
const enhancers = compose(applyMiddleware(createSagaMiddleware()));
|
||||||
|
export const mockedStore = createStore(reducers, enhancers);
|
|
@ -0,0 +1,36 @@
|
||||||
|
import { addUser, reset, setLoading, removeUser } from '../actions/selectedUsers';
|
||||||
|
import { mockedStore } from './mockedStore';
|
||||||
|
import { initialState } from './selectedUsers';
|
||||||
|
|
||||||
|
describe('test selectedUsers reducer', () => {
|
||||||
|
it('should return initial state', () => {
|
||||||
|
const state = mockedStore.getState().selectedUsers;
|
||||||
|
expect(state).toEqual(initialState);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return modified store after addUser', () => {
|
||||||
|
const user = { _id: 'xxx', name: 'xxx', fname: 'xxx' };
|
||||||
|
mockedStore.dispatch(addUser(user));
|
||||||
|
const state = mockedStore.getState().selectedUsers.users;
|
||||||
|
expect(state).toEqual([user]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return empty store after remove user', () => {
|
||||||
|
const user = { _id: 'xxx', name: 'xxx', fname: 'xxx' };
|
||||||
|
mockedStore.dispatch(removeUser(user));
|
||||||
|
const state = mockedStore.getState().selectedUsers.users;
|
||||||
|
expect(state).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return initial state after reset', () => {
|
||||||
|
mockedStore.dispatch(reset());
|
||||||
|
const state = mockedStore.getState().selectedUsers;
|
||||||
|
expect(state).toEqual(initialState);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return loading after call action', () => {
|
||||||
|
mockedStore.dispatch(setLoading(true));
|
||||||
|
const state = mockedStore.getState().selectedUsers.loading;
|
||||||
|
expect(state).toEqual(true);
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,11 +1,26 @@
|
||||||
|
import { TApplicationActions } from '../definitions';
|
||||||
import { SELECTED_USERS } from '../actions/actionsTypes';
|
import { SELECTED_USERS } from '../actions/actionsTypes';
|
||||||
|
|
||||||
const initialState = {
|
export interface ISelectedUser {
|
||||||
|
_id: string;
|
||||||
|
name: string;
|
||||||
|
fname: string;
|
||||||
|
search?: boolean;
|
||||||
|
// username is used when is from searching
|
||||||
|
username?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ISelectedUsers {
|
||||||
|
users: ISelectedUser[];
|
||||||
|
loading: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const initialState: ISelectedUsers = {
|
||||||
users: [],
|
users: [],
|
||||||
loading: false
|
loading: false
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function (state = initialState, action) {
|
export default function (state = initialState, action: TApplicationActions): ISelectedUsers {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case SELECTED_USERS.ADD_USER:
|
case SELECTED_USERS.ADD_USER:
|
||||||
return {
|
return {
|
|
@ -8,11 +8,12 @@ import { inviteLinksRequest, inviteLinksSetToken } from '../actions/inviteLinks'
|
||||||
import database from '../lib/database';
|
import database from '../lib/database';
|
||||||
import RocketChat from '../lib/rocketchat';
|
import RocketChat from '../lib/rocketchat';
|
||||||
import EventEmitter from '../utils/events';
|
import EventEmitter from '../utils/events';
|
||||||
import { ROOT_INSIDE, ROOT_OUTSIDE, appInit, appStart } from '../actions/app';
|
import { appInit, appStart } from '../actions/app';
|
||||||
import { localAuthenticate } from '../utils/localAuthentication';
|
import { localAuthenticate } from '../utils/localAuthentication';
|
||||||
import { goRoom } from '../utils/goRoom';
|
import { goRoom } from '../utils/goRoom';
|
||||||
import { loginRequest } from '../actions/login';
|
import { loginRequest } from '../actions/login';
|
||||||
import log from '../utils/log';
|
import log from '../utils/log';
|
||||||
|
import { RootEnum } from '../definitions';
|
||||||
|
|
||||||
const roomTypes = {
|
const roomTypes = {
|
||||||
channel: 'c',
|
channel: 'c',
|
||||||
|
@ -41,7 +42,7 @@ const popToRoot = function popToRoot({ isMasterDetail }) {
|
||||||
};
|
};
|
||||||
|
|
||||||
const navigate = function* navigate({ params }) {
|
const navigate = function* navigate({ params }) {
|
||||||
yield put(appStart({ root: ROOT_INSIDE }));
|
yield put(appStart({ root: RootEnum.ROOT_INSIDE }));
|
||||||
if (params.path || params.rid) {
|
if (params.path || params.rid) {
|
||||||
let type;
|
let type;
|
||||||
let name;
|
let name;
|
||||||
|
@ -192,7 +193,7 @@ const handleOpen = function* handleOpen({ params }) {
|
||||||
yield fallbackNavigation();
|
yield fallbackNavigation();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
yield put(appStart({ root: ROOT_OUTSIDE }));
|
yield put(appStart({ root: RootEnum.ROOT_OUTSIDE }));
|
||||||
yield put(serverInitAdd(server));
|
yield put(serverInitAdd(server));
|
||||||
yield delay(1000);
|
yield delay(1000);
|
||||||
EventEmitter.emit('NewServer', { server: host });
|
EventEmitter.emit('NewServer', { server: host });
|
||||||
|
|
|
@ -9,7 +9,8 @@ import RocketChat from '../lib/rocketchat';
|
||||||
import log from '../utils/log';
|
import log from '../utils/log';
|
||||||
import database from '../lib/database';
|
import database from '../lib/database';
|
||||||
import { localAuthenticate } from '../utils/localAuthentication';
|
import { localAuthenticate } from '../utils/localAuthentication';
|
||||||
import { ROOT_OUTSIDE, appReady, appStart } from '../actions/app';
|
import { appReady, appStart } from '../actions/app';
|
||||||
|
import { RootEnum } from '../definitions';
|
||||||
|
|
||||||
export const initLocalSettings = function* initLocalSettings() {
|
export const initLocalSettings = function* initLocalSettings() {
|
||||||
const sortPreferences = yield RocketChat.getSortPreferences();
|
const sortPreferences = yield RocketChat.getSortPreferences();
|
||||||
|
@ -22,7 +23,7 @@ const restore = function* restore() {
|
||||||
let userId = yield UserPreferences.getStringAsync(`${RocketChat.TOKEN_KEY}-${server}`);
|
let userId = yield UserPreferences.getStringAsync(`${RocketChat.TOKEN_KEY}-${server}`);
|
||||||
|
|
||||||
if (!server) {
|
if (!server) {
|
||||||
yield put(appStart({ root: ROOT_OUTSIDE }));
|
yield put(appStart({ root: RootEnum.ROOT_OUTSIDE }));
|
||||||
} else if (!userId) {
|
} else if (!userId) {
|
||||||
const serversDB = database.servers;
|
const serversDB = database.servers;
|
||||||
const serversCollection = serversDB.get('servers');
|
const serversCollection = serversDB.get('servers');
|
||||||
|
@ -38,7 +39,7 @@ const restore = function* restore() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
yield put(appStart({ root: ROOT_OUTSIDE }));
|
yield put(appStart({ root: RootEnum.ROOT_OUTSIDE }));
|
||||||
} else {
|
} else {
|
||||||
const serversDB = database.servers;
|
const serversDB = database.servers;
|
||||||
const serverCollections = serversDB.get('servers');
|
const serverCollections = serversDB.get('servers');
|
||||||
|
@ -56,7 +57,7 @@ const restore = function* restore() {
|
||||||
yield put(appReady({}));
|
yield put(appReady({}));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log(e);
|
log(e);
|
||||||
yield put(appStart({ root: ROOT_OUTSIDE }));
|
yield put(appStart({ root: RootEnum.ROOT_OUTSIDE }));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
|
||||||
import { Q } from '@nozbe/watermelondb';
|
import { Q } from '@nozbe/watermelondb';
|
||||||
|
|
||||||
import * as types from '../actions/actionsTypes';
|
import * as types from '../actions/actionsTypes';
|
||||||
import { ROOT_INSIDE, ROOT_LOADING, ROOT_OUTSIDE, ROOT_SET_USERNAME, appStart } from '../actions/app';
|
import { appStart } from '../actions/app';
|
||||||
import { selectServerRequest, serverFinishAdd } from '../actions/server';
|
import { selectServerRequest, serverFinishAdd } from '../actions/server';
|
||||||
import { loginFailure, loginSuccess, logout, setUser } from '../actions/login';
|
import { loginFailure, loginSuccess, logout, setUser } from '../actions/login';
|
||||||
import { roomsRequest } from '../actions/rooms';
|
import { roomsRequest } from '../actions/rooms';
|
||||||
|
@ -20,6 +20,7 @@ import { encryptionInit, encryptionStop } from '../actions/encryption';
|
||||||
import UserPreferences from '../lib/userPreferences';
|
import UserPreferences from '../lib/userPreferences';
|
||||||
import { inquiryRequest, inquiryReset } from '../ee/omnichannel/actions/inquiry';
|
import { inquiryRequest, inquiryReset } from '../ee/omnichannel/actions/inquiry';
|
||||||
import { isOmnichannelStatusAvailable } from '../ee/omnichannel/lib';
|
import { isOmnichannelStatusAvailable } from '../ee/omnichannel/lib';
|
||||||
|
import { RootEnum } from '../definitions';
|
||||||
|
|
||||||
const getServer = state => state.server.server;
|
const getServer = state => state.server.server;
|
||||||
const loginWithPasswordCall = args => RocketChat.loginWithPassword(args);
|
const loginWithPasswordCall = args => RocketChat.loginWithPassword(args);
|
||||||
|
@ -38,7 +39,7 @@ const handleLoginRequest = function* handleLoginRequest({ credentials, logoutOnE
|
||||||
if (!result.username) {
|
if (!result.username) {
|
||||||
yield put(serverFinishAdd());
|
yield put(serverFinishAdd());
|
||||||
yield put(setUser(result));
|
yield put(setUser(result));
|
||||||
yield put(appStart({ root: ROOT_SET_USERNAME }));
|
yield put(appStart({ root: RootEnum.ROOT_SET_USERNAME }));
|
||||||
} else {
|
} else {
|
||||||
const server = yield select(getServer);
|
const server = yield select(getServer);
|
||||||
yield localAuthenticate(server);
|
yield localAuthenticate(server);
|
||||||
|
@ -167,7 +168,7 @@ const handleLoginSuccess = function* handleLoginSuccess({ user }) {
|
||||||
yield put(setUser(user));
|
yield put(setUser(user));
|
||||||
EventEmitter.emit('connected');
|
EventEmitter.emit('connected');
|
||||||
|
|
||||||
yield put(appStart({ root: ROOT_INSIDE }));
|
yield put(appStart({ root: RootEnum.ROOT_INSIDE }));
|
||||||
const inviteLinkToken = yield select(state => state.inviteLinks.token);
|
const inviteLinkToken = yield select(state => state.inviteLinks.token);
|
||||||
if (inviteLinkToken) {
|
if (inviteLinkToken) {
|
||||||
yield put(inviteLinksRequest(inviteLinkToken));
|
yield put(inviteLinksRequest(inviteLinkToken));
|
||||||
|
@ -179,7 +180,7 @@ const handleLoginSuccess = function* handleLoginSuccess({ user }) {
|
||||||
|
|
||||||
const handleLogout = function* handleLogout({ forcedByServer }) {
|
const handleLogout = function* handleLogout({ forcedByServer }) {
|
||||||
yield put(encryptionStop());
|
yield put(encryptionStop());
|
||||||
yield put(appStart({ root: ROOT_LOADING, text: I18n.t('Logging_out') }));
|
yield put(appStart({ root: RootEnum.ROOT_LOADING, text: I18n.t('Logging_out') }));
|
||||||
const server = yield select(getServer);
|
const server = yield select(getServer);
|
||||||
if (server) {
|
if (server) {
|
||||||
try {
|
try {
|
||||||
|
@ -187,7 +188,7 @@ const handleLogout = function* handleLogout({ forcedByServer }) {
|
||||||
|
|
||||||
// if the user was logged out by the server
|
// if the user was logged out by the server
|
||||||
if (forcedByServer) {
|
if (forcedByServer) {
|
||||||
yield put(appStart({ root: ROOT_OUTSIDE }));
|
yield put(appStart({ root: RootEnum.ROOT_OUTSIDE }));
|
||||||
showErrorAlert(I18n.t('Logged_out_by_server'), I18n.t('Oops'));
|
showErrorAlert(I18n.t('Logged_out_by_server'), I18n.t('Oops'));
|
||||||
yield delay(300);
|
yield delay(300);
|
||||||
EventEmitter.emit('NewServer', { server });
|
EventEmitter.emit('NewServer', { server });
|
||||||
|
@ -209,10 +210,10 @@ const handleLogout = function* handleLogout({ forcedByServer }) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if there's no servers, go outside
|
// if there's no servers, go outside
|
||||||
yield put(appStart({ root: ROOT_OUTSIDE }));
|
yield put(appStart({ root: RootEnum.ROOT_OUTSIDE }));
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
yield put(appStart({ root: ROOT_OUTSIDE }));
|
yield put(appStart({ root: RootEnum.ROOT_OUTSIDE }));
|
||||||
log(e);
|
log(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,11 +15,12 @@ import database from '../lib/database';
|
||||||
import log, { logServerVersion } from '../utils/log';
|
import log, { logServerVersion } from '../utils/log';
|
||||||
import I18n from '../i18n';
|
import I18n from '../i18n';
|
||||||
import { BASIC_AUTH_KEY, setBasicAuth } from '../utils/fetch';
|
import { BASIC_AUTH_KEY, setBasicAuth } from '../utils/fetch';
|
||||||
import { ROOT_INSIDE, ROOT_OUTSIDE, appStart } from '../actions/app';
|
import { appStart } from '../actions/app';
|
||||||
import UserPreferences from '../lib/userPreferences';
|
import UserPreferences from '../lib/userPreferences';
|
||||||
import { encryptionStop } from '../actions/encryption';
|
import { encryptionStop } from '../actions/encryption';
|
||||||
import SSLPinning from '../utils/sslPinning';
|
import SSLPinning from '../utils/sslPinning';
|
||||||
import { inquiryReset } from '../ee/omnichannel/actions/inquiry';
|
import { inquiryReset } from '../ee/omnichannel/actions/inquiry';
|
||||||
|
import { RootEnum } from '../definitions';
|
||||||
|
|
||||||
const getServerInfo = function* getServerInfo({ server, raiseError = true }) {
|
const getServerInfo = function* getServerInfo({ server, raiseError = true }) {
|
||||||
try {
|
try {
|
||||||
|
@ -111,10 +112,10 @@ const handleSelectServer = function* handleSelectServer({ server, version, fetch
|
||||||
yield put(clearSettings());
|
yield put(clearSettings());
|
||||||
yield RocketChat.connect({ server, user, logoutOnError: true });
|
yield RocketChat.connect({ server, user, logoutOnError: true });
|
||||||
yield put(setUser(user));
|
yield put(setUser(user));
|
||||||
yield put(appStart({ root: ROOT_INSIDE }));
|
yield put(appStart({ root: RootEnum.ROOT_INSIDE }));
|
||||||
} else {
|
} else {
|
||||||
yield RocketChat.connect({ server });
|
yield RocketChat.connect({ server });
|
||||||
yield put(appStart({ root: ROOT_OUTSIDE }));
|
yield put(appStart({ root: RootEnum.ROOT_OUTSIDE }));
|
||||||
}
|
}
|
||||||
|
|
||||||
// We can't use yield here because fetch of Settings & Custom Emojis is slower
|
// We can't use yield here because fetch of Settings & Custom Emojis is slower
|
||||||
|
|
|
@ -5,11 +5,11 @@ import { setBadgeCount } from '../notifications/push';
|
||||||
import log from '../utils/log';
|
import log from '../utils/log';
|
||||||
import { localAuthenticate, saveLastLocalAuthenticationSession } from '../utils/localAuthentication';
|
import { localAuthenticate, saveLastLocalAuthenticationSession } from '../utils/localAuthentication';
|
||||||
import { APP_STATE } from '../actions/actionsTypes';
|
import { APP_STATE } from '../actions/actionsTypes';
|
||||||
import { ROOT_OUTSIDE } from '../actions/app';
|
import { RootEnum } from '../definitions';
|
||||||
|
|
||||||
const appHasComeBackToForeground = function* appHasComeBackToForeground() {
|
const appHasComeBackToForeground = function* appHasComeBackToForeground() {
|
||||||
const appRoot = yield select(state => state.app.root);
|
const appRoot = yield select(state => state.app.root);
|
||||||
if (appRoot === ROOT_OUTSIDE) {
|
if (appRoot === RootEnum.ROOT_OUTSIDE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const login = yield select(state => state.login);
|
const login = yield select(state => state.login);
|
||||||
|
@ -29,7 +29,7 @@ const appHasComeBackToForeground = function* appHasComeBackToForeground() {
|
||||||
|
|
||||||
const appHasComeBackToBackground = function* appHasComeBackToBackground() {
|
const appHasComeBackToBackground = function* appHasComeBackToBackground() {
|
||||||
const appRoot = yield select(state => state.app.root);
|
const appRoot = yield select(state => state.app.root);
|
||||||
if (appRoot === ROOT_OUTSIDE) {
|
if (appRoot === RootEnum.ROOT_OUTSIDE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -13,10 +13,11 @@ import StatusBar from '../../containers/StatusBar';
|
||||||
import * as List from '../../containers/List';
|
import * as List from '../../containers/List';
|
||||||
import { themes } from '../../constants/colors';
|
import { themes } from '../../constants/colors';
|
||||||
import { withTheme } from '../../theme';
|
import { withTheme } from '../../theme';
|
||||||
import { ROOT_INSIDE, ROOT_LOADING, appStart as appStartAction } from '../../actions/app';
|
import { appStart as appStartAction } from '../../actions/app';
|
||||||
import { getUserSelector } from '../../selectors/login';
|
import { getUserSelector } from '../../selectors/login';
|
||||||
import database from '../../lib/database';
|
import database from '../../lib/database';
|
||||||
import SafeAreaView from '../../containers/SafeAreaView';
|
import SafeAreaView from '../../containers/SafeAreaView';
|
||||||
|
import { RootEnum } from '../../definitions';
|
||||||
|
|
||||||
interface ILanguageViewProps {
|
interface ILanguageViewProps {
|
||||||
user: {
|
user: {
|
||||||
|
@ -73,7 +74,7 @@ class LanguageView extends React.Component<ILanguageViewProps, ILanguageViewStat
|
||||||
|
|
||||||
const shouldRestart = isRTL(language) || isRTL(user.language);
|
const shouldRestart = isRTL(language) || isRTL(user.language);
|
||||||
|
|
||||||
await appStart({ root: ROOT_LOADING, text: I18n.t('Change_language_loading') });
|
await appStart({ root: RootEnum.ROOT_LOADING, text: I18n.t('Change_language_loading') });
|
||||||
|
|
||||||
// shows loading for at least 300ms
|
// shows loading for at least 300ms
|
||||||
await Promise.all([this.changeLanguage(language), new Promise(resolve => setTimeout(resolve, 300))]);
|
await Promise.all([this.changeLanguage(language), new Promise(resolve => setTimeout(resolve, 300))]);
|
||||||
|
@ -81,7 +82,7 @@ class LanguageView extends React.Component<ILanguageViewProps, ILanguageViewStat
|
||||||
if (shouldRestart) {
|
if (shouldRestart) {
|
||||||
await RNRestart.Restart();
|
await RNRestart.Restart();
|
||||||
} else {
|
} else {
|
||||||
await appStart({ root: ROOT_INSIDE });
|
await appStart({ root: RootEnum.ROOT_INSIDE });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import * as List from '../../containers/List';
|
||||||
import Button from '../../containers/Button';
|
import Button from '../../containers/Button';
|
||||||
import { toggleServerDropdown as toggleServerDropdownAction } from '../../actions/rooms';
|
import { toggleServerDropdown as toggleServerDropdownAction } from '../../actions/rooms';
|
||||||
import { selectServerRequest as selectServerRequestAction, serverInitAdd as serverInitAddAction } from '../../actions/server';
|
import { selectServerRequest as selectServerRequestAction, serverInitAdd as serverInitAddAction } from '../../actions/server';
|
||||||
import { appStart as appStartAction, ROOT_OUTSIDE } from '../../actions/app';
|
import { appStart as appStartAction } from '../../actions/app';
|
||||||
import RocketChat from '../../lib/rocketchat';
|
import RocketChat from '../../lib/rocketchat';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
import EventEmitter from '../../utils/events';
|
import EventEmitter from '../../utils/events';
|
||||||
|
@ -24,6 +24,8 @@ import log, { events, logEvent } from '../../utils/log';
|
||||||
import { headerHeight } from '../../containers/Header';
|
import { headerHeight } from '../../containers/Header';
|
||||||
import { goRoom } from '../../utils/goRoom';
|
import { goRoom } from '../../utils/goRoom';
|
||||||
import UserPreferences from '../../lib/userPreferences';
|
import UserPreferences from '../../lib/userPreferences';
|
||||||
|
import { RootEnum } from '../../definitions';
|
||||||
|
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
|
|
||||||
const ROW_HEIGHT = 68;
|
const ROW_HEIGHT = 68;
|
||||||
|
@ -110,7 +112,7 @@ class ServerDropdown extends Component {
|
||||||
navToNewServer = previousServer => {
|
navToNewServer = previousServer => {
|
||||||
const { appStart, initAdd } = this.props;
|
const { appStart, initAdd } = this.props;
|
||||||
batch(() => {
|
batch(() => {
|
||||||
appStart({ root: ROOT_OUTSIDE });
|
appStart({ root: RootEnum.ROOT_OUTSIDE });
|
||||||
initAdd(previousServer);
|
initAdd(previousServer);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -50,6 +50,8 @@ import { E2E_BANNER_TYPE } from '../../lib/encryption/constants';
|
||||||
import { getInquiryQueueSelector } from '../../ee/omnichannel/selectors/inquiry';
|
import { getInquiryQueueSelector } from '../../ee/omnichannel/selectors/inquiry';
|
||||||
import { changeLivechatStatus, isOmnichannelStatusAvailable } from '../../ee/omnichannel/lib';
|
import { changeLivechatStatus, isOmnichannelStatusAvailable } from '../../ee/omnichannel/lib';
|
||||||
import { DISPLAY_MODE_CONDENSED } from '../../constants/constantDisplayMode';
|
import { DISPLAY_MODE_CONDENSED } from '../../constants/constantDisplayMode';
|
||||||
|
import { RootEnum } from '../../definitions';
|
||||||
|
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
import ServerDropdown from './ServerDropdown';
|
import ServerDropdown from './ServerDropdown';
|
||||||
import ListHeader from './ListHeader';
|
import ListHeader from './ListHeader';
|
||||||
|
@ -862,7 +864,7 @@ class RoomsListView extends React.Component {
|
||||||
}
|
}
|
||||||
} else if (handleCommandAddNewServer(event)) {
|
} else if (handleCommandAddNewServer(event)) {
|
||||||
batch(() => {
|
batch(() => {
|
||||||
appStart({ root: ROOT_OUTSIDE });
|
appStart({ root: RootEnum.ROOT_OUTSIDE });
|
||||||
initAdd(server);
|
initAdd(server);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,56 +1,43 @@
|
||||||
|
import { Q } from '@nozbe/watermelondb';
|
||||||
|
import orderBy from 'lodash/orderBy';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { StackNavigationProp } from '@react-navigation/stack';
|
|
||||||
import { RouteProp } from '@react-navigation/native';
|
|
||||||
import { FlatList, View } from 'react-native';
|
import { FlatList, View } from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import orderBy from 'lodash/orderBy';
|
|
||||||
import { Q } from '@nozbe/watermelondb';
|
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
|
import { addUser, removeUser, reset } from '../actions/selectedUsers';
|
||||||
|
import { themes } from '../constants/colors';
|
||||||
|
import * as HeaderButton from '../containers/HeaderButton';
|
||||||
import * as List from '../containers/List';
|
import * as List from '../containers/List';
|
||||||
|
import Loading from '../containers/Loading';
|
||||||
|
import SafeAreaView from '../containers/SafeAreaView';
|
||||||
|
import SearchBox from '../containers/SearchBox';
|
||||||
|
import StatusBar from '../containers/StatusBar';
|
||||||
|
import { IApplicationState, IBaseScreen } from '../definitions';
|
||||||
|
import I18n from '../i18n';
|
||||||
import database from '../lib/database';
|
import database from '../lib/database';
|
||||||
import RocketChat from '../lib/rocketchat';
|
import RocketChat from '../lib/rocketchat';
|
||||||
import UserItem from '../presentation/UserItem';
|
import UserItem from '../presentation/UserItem';
|
||||||
import Loading from '../containers/Loading';
|
import { ISelectedUser } from '../reducers/selectedUsers';
|
||||||
import I18n from '../i18n';
|
|
||||||
import log, { events, logEvent } from '../utils/log';
|
|
||||||
import SearchBox from '../containers/SearchBox';
|
|
||||||
import * as HeaderButton from '../containers/HeaderButton';
|
|
||||||
import StatusBar from '../containers/StatusBar';
|
|
||||||
import { themes } from '../constants/colors';
|
|
||||||
import { withTheme } from '../theme';
|
|
||||||
import { getUserSelector } from '../selectors/login';
|
import { getUserSelector } from '../selectors/login';
|
||||||
import { addUser as addUserAction, removeUser as removeUserAction, reset as resetAction } from '../actions/selectedUsers';
|
|
||||||
import { showErrorAlert } from '../utils/info';
|
|
||||||
import SafeAreaView from '../containers/SafeAreaView';
|
|
||||||
import sharedStyles from './Styles';
|
|
||||||
import { ChatsStackParamList } from '../stacks/types';
|
import { ChatsStackParamList } from '../stacks/types';
|
||||||
|
import { withTheme } from '../theme';
|
||||||
|
import { showErrorAlert } from '../utils/info';
|
||||||
|
import log, { events, logEvent } from '../utils/log';
|
||||||
|
import sharedStyles from './Styles';
|
||||||
|
|
||||||
const ITEM_WIDTH = 250;
|
const ITEM_WIDTH = 250;
|
||||||
const getItemLayout = (_: any, index: number) => ({ length: ITEM_WIDTH, offset: ITEM_WIDTH * index, index });
|
const getItemLayout = (_: any, index: number) => ({ length: ITEM_WIDTH, offset: ITEM_WIDTH * index, index });
|
||||||
|
|
||||||
interface IUser {
|
|
||||||
_id: string;
|
|
||||||
name: string;
|
|
||||||
fname: string;
|
|
||||||
search?: boolean;
|
|
||||||
// username is used when is from searching
|
|
||||||
username?: string;
|
|
||||||
}
|
|
||||||
interface ISelectedUsersViewState {
|
interface ISelectedUsersViewState {
|
||||||
maxUsers?: number;
|
maxUsers?: number;
|
||||||
search: IUser[];
|
search: ISelectedUser[];
|
||||||
chats: IUser[];
|
chats: ISelectedUser[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ISelectedUsersViewProps {
|
interface ISelectedUsersViewProps extends IBaseScreen<ChatsStackParamList, 'SelectedUsersView'> {
|
||||||
navigation: StackNavigationProp<ChatsStackParamList, 'SelectedUsersView'>;
|
// REDUX STATE
|
||||||
route: RouteProp<ChatsStackParamList, 'SelectedUsersView'>;
|
users: ISelectedUser[];
|
||||||
baseUrl: string;
|
|
||||||
addUser(user: IUser): void;
|
|
||||||
removeUser(user: IUser): void;
|
|
||||||
reset(): void;
|
|
||||||
users: IUser[];
|
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
user: {
|
user: {
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -58,7 +45,7 @@ interface ISelectedUsersViewProps {
|
||||||
username: string;
|
username: string;
|
||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
theme: string;
|
baseUrl: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
class SelectedUsersView extends React.Component<ISelectedUsersViewProps, ISelectedUsersViewState> {
|
class SelectedUsersView extends React.Component<ISelectedUsersViewProps, ISelectedUsersViewState> {
|
||||||
|
@ -75,9 +62,9 @@ class SelectedUsersView extends React.Component<ISelectedUsersViewProps, ISelect
|
||||||
search: [],
|
search: [],
|
||||||
chats: []
|
chats: []
|
||||||
};
|
};
|
||||||
const { user } = this.props;
|
const { user, dispatch } = this.props;
|
||||||
if (this.isGroupChat()) {
|
if (this.isGroupChat()) {
|
||||||
props.addUser({ _id: user.id, name: user.username, fname: user.name });
|
dispatch(addUser({ _id: user.id, name: user.username, fname: user.name }));
|
||||||
}
|
}
|
||||||
this.setHeader(props.route.params?.showButton);
|
this.setHeader(props.route.params?.showButton);
|
||||||
}
|
}
|
||||||
|
@ -92,8 +79,8 @@ class SelectedUsersView extends React.Component<ISelectedUsersViewProps, ISelect
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
const { reset } = this.props;
|
const { dispatch } = this.props;
|
||||||
reset();
|
dispatch(reset());
|
||||||
if (this.querySubscription && this.querySubscription.unsubscribe) {
|
if (this.querySubscription && this.querySubscription.unsubscribe) {
|
||||||
this.querySubscription.unsubscribe();
|
this.querySubscription.unsubscribe();
|
||||||
}
|
}
|
||||||
|
@ -158,11 +145,10 @@ class SelectedUsersView extends React.Component<ISelectedUsersViewProps, ISelect
|
||||||
return users.findIndex(el => el.name === username) !== -1;
|
return users.findIndex(el => el.name === username) !== -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
toggleUser = (user: IUser) => {
|
toggleUser = (user: ISelectedUser) => {
|
||||||
const { maxUsers } = this.state;
|
const { maxUsers } = this.state;
|
||||||
const {
|
const {
|
||||||
addUser,
|
dispatch,
|
||||||
removeUser,
|
|
||||||
users,
|
users,
|
||||||
user: { username }
|
user: { username }
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
@ -177,14 +163,14 @@ class SelectedUsersView extends React.Component<ISelectedUsersViewProps, ISelect
|
||||||
return showErrorAlert(I18n.t('Max_number_of_users_allowed_is_number', { maxUsers }), I18n.t('Oops'));
|
return showErrorAlert(I18n.t('Max_number_of_users_allowed_is_number', { maxUsers }), I18n.t('Oops'));
|
||||||
}
|
}
|
||||||
logEvent(events.SELECTED_USERS_ADD_USER);
|
logEvent(events.SELECTED_USERS_ADD_USER);
|
||||||
addUser(user);
|
dispatch(addUser(user));
|
||||||
} else {
|
} else {
|
||||||
logEvent(events.SELECTED_USERS_REMOVE_USER);
|
logEvent(events.SELECTED_USERS_REMOVE_USER);
|
||||||
removeUser(user);
|
dispatch(removeUser(user));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_onPressItem = (id: string, item = {} as IUser) => {
|
_onPressItem = (id: string, item = {} as ISelectedUser) => {
|
||||||
if (item.search) {
|
if (item.search) {
|
||||||
this.toggleUser({ _id: item._id, name: item.username!, fname: item.name });
|
this.toggleUser({ _id: item._id, name: item.username!, fname: item.name });
|
||||||
} else {
|
} else {
|
||||||
|
@ -192,7 +178,7 @@ class SelectedUsersView extends React.Component<ISelectedUsersViewProps, ISelect
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_onPressSelectedItem = (item: IUser) => this.toggleUser(item);
|
_onPressSelectedItem = (item: ISelectedUser) => this.toggleUser(item);
|
||||||
|
|
||||||
renderHeader = () => {
|
renderHeader = () => {
|
||||||
const { theme } = this.props;
|
const { theme } = this.props;
|
||||||
|
@ -231,7 +217,7 @@ class SelectedUsersView extends React.Component<ISelectedUsersViewProps, ISelect
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
renderSelectedItem = ({ item }: { item: IUser }) => {
|
renderSelectedItem = ({ item }: { item: ISelectedUser }) => {
|
||||||
const { theme } = this.props;
|
const { theme } = this.props;
|
||||||
return (
|
return (
|
||||||
<UserItem
|
<UserItem
|
||||||
|
@ -245,7 +231,7 @@ class SelectedUsersView extends React.Component<ISelectedUsersViewProps, ISelect
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
renderItem = ({ item, index }: { item: IUser; index: number }) => {
|
renderItem = ({ item, index }: { item: ISelectedUser; index: number }) => {
|
||||||
const { search, chats } = this.state;
|
const { search, chats } = this.state;
|
||||||
const { theme } = this.props;
|
const { theme } = this.props;
|
||||||
|
|
||||||
|
@ -308,17 +294,11 @@ class SelectedUsersView extends React.Component<ISelectedUsersViewProps, ISelect
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = (state: any) => ({
|
const mapStateToProps = (state: IApplicationState) => ({
|
||||||
baseUrl: state.server.server,
|
baseUrl: state.server.server,
|
||||||
users: state.selectedUsers.users,
|
users: state.selectedUsers.users,
|
||||||
loading: state.selectedUsers.loading,
|
loading: state.selectedUsers.loading,
|
||||||
user: getUserSelector(state)
|
user: getUserSelector(state)
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch: any) => ({
|
export default connect(mapStateToProps)(withTheme(SelectedUsersView));
|
||||||
addUser: (user: any) => dispatch(addUserAction(user)),
|
|
||||||
removeUser: (user: any) => dispatch(removeUserAction(user)),
|
|
||||||
reset: () => dispatch(resetAction())
|
|
||||||
});
|
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(withTheme(SelectedUsersView));
|
|
||||||
|
|
|
@ -23,12 +23,13 @@ import { withTheme } from '../../theme';
|
||||||
import SidebarView from '../SidebarView';
|
import SidebarView from '../SidebarView';
|
||||||
import { LISTENER } from '../../containers/Toast';
|
import { LISTENER } from '../../containers/Toast';
|
||||||
import EventEmitter from '../../utils/events';
|
import EventEmitter from '../../utils/events';
|
||||||
import { ROOT_LOADING, appStart as appStartAction } from '../../actions/app';
|
import { appStart as appStartAction } from '../../actions/app';
|
||||||
import { onReviewPress } from '../../utils/review';
|
import { onReviewPress } from '../../utils/review';
|
||||||
import SafeAreaView from '../../containers/SafeAreaView';
|
import SafeAreaView from '../../containers/SafeAreaView';
|
||||||
import database from '../../lib/database';
|
import database from '../../lib/database';
|
||||||
import { isFDroidBuild } from '../../constants/environment';
|
import { isFDroidBuild } from '../../constants/environment';
|
||||||
import { getUserSelector } from '../../selectors/login';
|
import { getUserSelector } from '../../selectors/login';
|
||||||
|
import { RootEnum } from '../../definitions';
|
||||||
|
|
||||||
interface ISettingsViewProps {
|
interface ISettingsViewProps {
|
||||||
navigation: StackNavigationProp<SettingsStackParamList, 'SettingsView'>;
|
navigation: StackNavigationProp<SettingsStackParamList, 'SettingsView'>;
|
||||||
|
@ -108,7 +109,7 @@ class SettingsView extends React.Component<ISettingsViewProps, any> {
|
||||||
appStart,
|
appStart,
|
||||||
selectServerRequest
|
selectServerRequest
|
||||||
} = this.props;
|
} = this.props;
|
||||||
appStart({ root: ROOT_LOADING, text: I18n.t('Clear_cache_loading') });
|
appStart({ root: RootEnum.ROOT_LOADING, text: I18n.t('Clear_cache_loading') });
|
||||||
await RocketChat.clearCache({ server });
|
await RocketChat.clearCache({ server });
|
||||||
await FastImage.clearMemoryCache();
|
await FastImage.clearMemoryCache();
|
||||||
await FastImage.clearDiskCache();
|
await FastImage.clearDiskCache();
|
||||||
|
|
|
@ -164,6 +164,7 @@
|
||||||
"eslint": "^7.31.0",
|
"eslint": "^7.31.0",
|
||||||
"eslint-config-prettier": "^8.3.0",
|
"eslint-config-prettier": "^8.3.0",
|
||||||
"eslint-plugin-import": "2.22.0",
|
"eslint-plugin-import": "2.22.0",
|
||||||
|
"eslint-plugin-jest": "24.7.0",
|
||||||
"eslint-plugin-jsx-a11y": "6.3.1",
|
"eslint-plugin-jsx-a11y": "6.3.1",
|
||||||
"eslint-plugin-react": "7.20.3",
|
"eslint-plugin-react": "7.20.3",
|
||||||
"eslint-plugin-react-native": "3.8.1",
|
"eslint-plugin-react-native": "3.8.1",
|
||||||
|
|
53
yarn.lock
53
yarn.lock
|
@ -4593,6 +4593,18 @@
|
||||||
eslint-scope "^5.1.1"
|
eslint-scope "^5.1.1"
|
||||||
eslint-utils "^3.0.0"
|
eslint-utils "^3.0.0"
|
||||||
|
|
||||||
|
"@typescript-eslint/experimental-utils@^4.0.1":
|
||||||
|
version "4.33.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz#6f2a786a4209fa2222989e9380b5331b2810f7fd"
|
||||||
|
integrity sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q==
|
||||||
|
dependencies:
|
||||||
|
"@types/json-schema" "^7.0.7"
|
||||||
|
"@typescript-eslint/scope-manager" "4.33.0"
|
||||||
|
"@typescript-eslint/types" "4.33.0"
|
||||||
|
"@typescript-eslint/typescript-estree" "4.33.0"
|
||||||
|
eslint-scope "^5.1.1"
|
||||||
|
eslint-utils "^3.0.0"
|
||||||
|
|
||||||
"@typescript-eslint/parser@^4.28.5":
|
"@typescript-eslint/parser@^4.28.5":
|
||||||
version "4.31.0"
|
version "4.31.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.31.0.tgz#87b7cd16b24b9170c77595d8b1363f8047121e05"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.31.0.tgz#87b7cd16b24b9170c77595d8b1363f8047121e05"
|
||||||
|
@ -4611,11 +4623,24 @@
|
||||||
"@typescript-eslint/types" "4.31.0"
|
"@typescript-eslint/types" "4.31.0"
|
||||||
"@typescript-eslint/visitor-keys" "4.31.0"
|
"@typescript-eslint/visitor-keys" "4.31.0"
|
||||||
|
|
||||||
|
"@typescript-eslint/scope-manager@4.33.0":
|
||||||
|
version "4.33.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz#d38e49280d983e8772e29121cf8c6e9221f280a3"
|
||||||
|
integrity sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==
|
||||||
|
dependencies:
|
||||||
|
"@typescript-eslint/types" "4.33.0"
|
||||||
|
"@typescript-eslint/visitor-keys" "4.33.0"
|
||||||
|
|
||||||
"@typescript-eslint/types@4.31.0":
|
"@typescript-eslint/types@4.31.0":
|
||||||
version "4.31.0"
|
version "4.31.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.31.0.tgz#9a7c86fcc1620189567dc4e46cad7efa07ee8dce"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.31.0.tgz#9a7c86fcc1620189567dc4e46cad7efa07ee8dce"
|
||||||
integrity sha512-9XR5q9mk7DCXgXLS7REIVs+BaAswfdHhx91XqlJklmqWpTALGjygWVIb/UnLh4NWhfwhR5wNe1yTyCInxVhLqQ==
|
integrity sha512-9XR5q9mk7DCXgXLS7REIVs+BaAswfdHhx91XqlJklmqWpTALGjygWVIb/UnLh4NWhfwhR5wNe1yTyCInxVhLqQ==
|
||||||
|
|
||||||
|
"@typescript-eslint/types@4.33.0":
|
||||||
|
version "4.33.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.33.0.tgz#a1e59036a3b53ae8430ceebf2a919dc7f9af6d72"
|
||||||
|
integrity sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==
|
||||||
|
|
||||||
"@typescript-eslint/typescript-estree@4.31.0":
|
"@typescript-eslint/typescript-estree@4.31.0":
|
||||||
version "4.31.0"
|
version "4.31.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.31.0.tgz#4da4cb6274a7ef3b21d53f9e7147cc76f278a078"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.31.0.tgz#4da4cb6274a7ef3b21d53f9e7147cc76f278a078"
|
||||||
|
@ -4629,6 +4654,19 @@
|
||||||
semver "^7.3.5"
|
semver "^7.3.5"
|
||||||
tsutils "^3.21.0"
|
tsutils "^3.21.0"
|
||||||
|
|
||||||
|
"@typescript-eslint/typescript-estree@4.33.0":
|
||||||
|
version "4.33.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz#0dfb51c2908f68c5c08d82aefeaf166a17c24609"
|
||||||
|
integrity sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==
|
||||||
|
dependencies:
|
||||||
|
"@typescript-eslint/types" "4.33.0"
|
||||||
|
"@typescript-eslint/visitor-keys" "4.33.0"
|
||||||
|
debug "^4.3.1"
|
||||||
|
globby "^11.0.3"
|
||||||
|
is-glob "^4.0.1"
|
||||||
|
semver "^7.3.5"
|
||||||
|
tsutils "^3.21.0"
|
||||||
|
|
||||||
"@typescript-eslint/visitor-keys@4.31.0":
|
"@typescript-eslint/visitor-keys@4.31.0":
|
||||||
version "4.31.0"
|
version "4.31.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.31.0.tgz#4e87b7761cb4e0e627dc2047021aa693fc76ea2b"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.31.0.tgz#4e87b7761cb4e0e627dc2047021aa693fc76ea2b"
|
||||||
|
@ -4637,6 +4675,14 @@
|
||||||
"@typescript-eslint/types" "4.31.0"
|
"@typescript-eslint/types" "4.31.0"
|
||||||
eslint-visitor-keys "^2.0.0"
|
eslint-visitor-keys "^2.0.0"
|
||||||
|
|
||||||
|
"@typescript-eslint/visitor-keys@4.33.0":
|
||||||
|
version "4.33.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz#2a22f77a41604289b7a186586e9ec48ca92ef1dd"
|
||||||
|
integrity sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==
|
||||||
|
dependencies:
|
||||||
|
"@typescript-eslint/types" "4.33.0"
|
||||||
|
eslint-visitor-keys "^2.0.0"
|
||||||
|
|
||||||
"@ungap/promise-all-settled@1.1.2":
|
"@ungap/promise-all-settled@1.1.2":
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44"
|
resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44"
|
||||||
|
@ -8145,6 +8191,13 @@ eslint-plugin-import@^2.17.2:
|
||||||
resolve "^1.20.0"
|
resolve "^1.20.0"
|
||||||
tsconfig-paths "^3.11.0"
|
tsconfig-paths "^3.11.0"
|
||||||
|
|
||||||
|
eslint-plugin-jest@24.7.0:
|
||||||
|
version "24.7.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-24.7.0.tgz#206ac0833841e59e375170b15f8d0955219c4889"
|
||||||
|
integrity sha512-wUxdF2bAZiYSKBclsUMrYHH6WxiBreNjyDxbRv345TIvPeoCEgPNEn3Sa+ZrSqsf1Dl9SqqSREXMHExlMMu1DA==
|
||||||
|
dependencies:
|
||||||
|
"@typescript-eslint/experimental-utils" "^4.0.1"
|
||||||
|
|
||||||
eslint-plugin-jsx-a11y@6.3.1:
|
eslint-plugin-jsx-a11y@6.3.1:
|
||||||
version "6.3.1"
|
version "6.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.3.1.tgz#99ef7e97f567cc6a5b8dd5ab95a94a67058a2660"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.3.1.tgz#99ef7e97f567cc6a5b8dd5ab95a94a67058a2660"
|
||||||
|
|
Loading…
Reference in New Issue