Merge pull request #3615 from RocketChat/chore/migration-ts-redux-rooms

Chore: migrate redux module room to typescript
This commit is contained in:
Gleidson Daniel Silva 2022-01-26 10:24:48 -03:00 committed by GitHub
commit 27369f60ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 212 additions and 144 deletions

View File

@ -1,58 +0,0 @@
import * as types from './actionsTypes';
export function roomsRequest(params = { allData: false }) {
return {
type: types.ROOMS.REQUEST,
params
};
}
export function roomsSuccess() {
return {
type: types.ROOMS.SUCCESS
};
}
export function roomsFailure(err) {
return {
type: types.ROOMS.FAILURE,
err
};
}
export function roomsRefresh() {
return {
type: types.ROOMS.REFRESH
};
}
export function setSearch(searchText) {
return {
type: types.ROOMS.SET_SEARCH,
searchText
};
}
export function closeServerDropdown() {
return {
type: types.ROOMS.CLOSE_SERVER_DROPDOWN
};
}
export function toggleServerDropdown() {
return {
type: types.ROOMS.TOGGLE_SERVER_DROPDOWN
};
}
export function openSearchHeader() {
return {
type: types.ROOMS.OPEN_SEARCH_HEADER
};
}
export function closeSearchHeader() {
return {
type: types.ROOMS.CLOSE_SEARCH_HEADER
};
}

78
app/actions/rooms.ts Normal file
View File

@ -0,0 +1,78 @@
import { Action } from 'redux';
import { ROOMS } from './actionsTypes';
export interface IRoomsRequest extends Action {
params: any;
}
export interface ISetSearch extends Action {
searchText: string;
}
export interface IRoomsFailure extends Action {
err: Record<string, any> | string;
}
export type IRoomsAction = IRoomsRequest & ISetSearch & IRoomsFailure;
export function roomsRequest(
params: {
allData: boolean;
} = { allData: false }
): IRoomsRequest {
return {
type: ROOMS.REQUEST,
params
};
}
export function roomsSuccess(): Action {
return {
type: ROOMS.SUCCESS
};
}
export function roomsFailure(err: string): IRoomsFailure {
return {
type: ROOMS.FAILURE,
err
};
}
export function roomsRefresh(): Action {
return {
type: ROOMS.REFRESH
};
}
export function setSearch(searchText: string): ISetSearch {
return {
type: ROOMS.SET_SEARCH,
searchText
};
}
export function closeServerDropdown(): Action {
return {
type: ROOMS.CLOSE_SERVER_DROPDOWN
};
}
export function toggleServerDropdown(): Action {
return {
type: ROOMS.TOGGLE_SERVER_DROPDOWN
};
}
export function openSearchHeader(): Action {
return {
type: ROOMS.OPEN_SEARCH_HEADER
};
}
export function closeSearchHeader(): Action {
return {
type: ROOMS.CLOSE_SEARCH_HEADER
};
}

View File

@ -0,0 +1,77 @@
import {
closeSearchHeader,
closeServerDropdown,
openSearchHeader,
roomsFailure,
roomsRefresh,
roomsRequest,
roomsSuccess,
setSearch,
toggleServerDropdown
} from '../actions/rooms';
import { mockedStore } from './mockedStore';
import { initialState } from './rooms';
describe('test selectedUsers reducer', () => {
it('should return initial state', () => {
const state = mockedStore.getState().rooms;
expect(state).toEqual(initialState);
});
it('should return modified store after call roomsRequest', () => {
mockedStore.dispatch(roomsRequest());
const state = mockedStore.getState().rooms;
const manipulated = { ...initialState, isFetching: true, failure: false, errorMessage: {} };
expect(state).toEqual(manipulated);
});
it('should return modified store after call roomsSuccess', () => {
mockedStore.dispatch(roomsSuccess());
const state = mockedStore.getState().rooms;
const manipulated = { ...initialState, isFetching: false, refreshing: false };
expect(state).toEqual(manipulated);
});
it('should return modified store after call roomsRefresh', () => {
mockedStore.dispatch(roomsRefresh());
const state = mockedStore.getState().rooms;
const manipulated = { ...initialState, isFetching: true, refreshing: true };
expect(state).toEqual(manipulated);
});
it('should return modified store after call setSearch', () => {
mockedStore.dispatch(setSearch('dog'));
const state = mockedStore.getState().rooms;
expect(state.searchText).toEqual('dog');
});
it('should return modified store after call closeServerDropdown', () => {
mockedStore.dispatch(closeServerDropdown());
const state = mockedStore.getState().rooms;
expect(state.closeServerDropdown).toEqual(!initialState.closeServerDropdown);
});
it('should return modified store after call toggleServerDropdown', () => {
mockedStore.dispatch(toggleServerDropdown());
const state = mockedStore.getState().rooms;
expect(state.showServerDropdown).toEqual(!initialState.showServerDropdown);
});
it('should return modified store after call openSearchHeader', () => {
mockedStore.dispatch(openSearchHeader());
const state = mockedStore.getState().rooms;
expect(state.showSearchHeader).toEqual(true);
});
it('should return modified store after call closeSearchHeader', () => {
mockedStore.dispatch(closeSearchHeader());
const state = mockedStore.getState().rooms;
expect(state.showSearchHeader).toEqual(false);
});
it('should return modified store after call roomsFailure', () => {
mockedStore.dispatch(roomsFailure('error'));
const state = mockedStore.getState().rooms;
expect(state.errorMessage).toEqual('error');
});
});

View File

@ -1,6 +1,18 @@
import * as types from '../actions/actionsTypes'; import { IRoomsAction } from '../actions/rooms';
import { ROOMS } from '../actions/actionsTypes';
const initialState = { export interface IRooms {
isFetching: boolean;
refreshing: boolean;
failure: boolean;
errorMessage: Record<string, any> | string;
searchText: string;
showServerDropdown: boolean;
closeServerDropdown: boolean;
showSearchHeader: boolean;
}
export const initialState: IRooms = {
isFetching: false, isFetching: false,
refreshing: false, refreshing: false,
failure: false, failure: false,
@ -11,22 +23,22 @@ const initialState = {
showSearchHeader: false showSearchHeader: false
}; };
export default function login(state = initialState, action) { export default function rooms(state = initialState, action: IRoomsAction): IRooms {
switch (action.type) { switch (action.type) {
case types.ROOMS.REQUEST: case ROOMS.REQUEST:
return { return {
...state, ...state,
isFetching: true, isFetching: true,
failure: false, failure: false,
errorMessage: {} errorMessage: {}
}; };
case types.ROOMS.SUCCESS: case ROOMS.SUCCESS:
return { return {
...state, ...state,
isFetching: false, isFetching: false,
refreshing: false refreshing: false
}; };
case types.ROOMS.FAILURE: case ROOMS.FAILURE:
return { return {
...state, ...state,
isFetching: false, isFetching: false,
@ -34,33 +46,33 @@ export default function login(state = initialState, action) {
failure: true, failure: true,
errorMessage: action.err errorMessage: action.err
}; };
case types.ROOMS.REFRESH: case ROOMS.REFRESH:
return { return {
...state, ...state,
isFetching: true, isFetching: true,
refreshing: true refreshing: true
}; };
case types.ROOMS.SET_SEARCH: case ROOMS.SET_SEARCH:
return { return {
...state, ...state,
searchText: action.searchText searchText: action.searchText
}; };
case types.ROOMS.CLOSE_SERVER_DROPDOWN: case ROOMS.CLOSE_SERVER_DROPDOWN:
return { return {
...state, ...state,
closeServerDropdown: !state.closeServerDropdown closeServerDropdown: !state.closeServerDropdown
}; };
case types.ROOMS.TOGGLE_SERVER_DROPDOWN: case ROOMS.TOGGLE_SERVER_DROPDOWN:
return { return {
...state, ...state,
showServerDropdown: !state.showServerDropdown showServerDropdown: !state.showServerDropdown
}; };
case types.ROOMS.OPEN_SEARCH_HEADER: case ROOMS.OPEN_SEARCH_HEADER:
return { return {
...state, ...state,
showSearchHeader: true showSearchHeader: true
}; };
case types.ROOMS.CLOSE_SEARCH_HEADER: case ROOMS.CLOSE_SEARCH_HEADER:
return { return {
...state, ...state,
showSearchHeader: false showSearchHeader: false

View File

@ -2,7 +2,7 @@ import React, { PureComponent } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { toggleServerDropdown, closeServerDropdown, setSearch as setSearchAction } from '../../../actions/rooms'; import { toggleServerDropdown, closeServerDropdown, setSearch } from '../../../actions/rooms';
import { withTheme } from '../../../theme'; import { withTheme } from '../../../theme';
import EventEmitter from '../../../utils/events'; import EventEmitter from '../../../utils/events';
import { KEY_COMMAND, handleCommandOpenServerDropdown } from '../../../commands'; import { KEY_COMMAND, handleCommandOpenServerDropdown } from '../../../commands';
@ -19,10 +19,7 @@ class RoomsListHeaderView extends PureComponent {
connected: PropTypes.bool, connected: PropTypes.bool,
isFetching: PropTypes.bool, isFetching: PropTypes.bool,
theme: PropTypes.string, theme: PropTypes.string,
server: PropTypes.string, server: PropTypes.string
open: PropTypes.func,
close: PropTypes.func,
setSearch: PropTypes.func
}; };
componentDidMount() { componentDidMount() {
@ -45,17 +42,17 @@ class RoomsListHeaderView extends PureComponent {
}; };
onSearchChangeText = text => { onSearchChangeText = text => {
const { setSearch } = this.props; const { dispatch } = this.props;
setSearch(text.trim()); dispatch(setSearch(text.trim()));
}; };
onPress = () => { onPress = () => {
logEvent(events.RL_TOGGLE_SERVER_DROPDOWN); logEvent(events.RL_TOGGLE_SERVER_DROPDOWN);
const { showServerDropdown, close, open } = this.props; const { showServerDropdown, dispatch } = this.props;
if (showServerDropdown) { if (showServerDropdown) {
close(); dispatch(closeServerDropdown());
} else { } else {
open(); dispatch(toggleServerDropdown());
} }
}; };
@ -89,10 +86,4 @@ const mapStateToProps = state => ({
server: state.server.server server: state.server.server
}); });
const mapDispatchtoProps = dispatch => ({ export default connect(mapStateToProps)(withTheme(RoomsListHeaderView));
close: () => dispatch(closeServerDropdown()),
open: () => dispatch(toggleServerDropdown()),
setSearch: searchText => dispatch(setSearchAction(searchText))
});
export default connect(mapStateToProps, mapDispatchtoProps)(withTheme(RoomsListHeaderView));

View File

@ -6,9 +6,9 @@ import { withSafeAreaInsets } from 'react-native-safe-area-context';
import * as List from '../../containers/List'; 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 } from '../../actions/rooms';
import { selectServerRequest as selectServerRequestAction, serverInitAdd as serverInitAddAction } from '../../actions/server'; import { selectServerRequest, serverInitAdd } from '../../actions/server';
import { appStart as appStartAction, ROOT_OUTSIDE } from '../../actions/app'; import { appStart, ROOT_OUTSIDE } 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';
@ -36,11 +36,7 @@ class ServerDropdown extends Component {
closeServerDropdown: PropTypes.bool, closeServerDropdown: PropTypes.bool,
server: PropTypes.string, server: PropTypes.string,
theme: PropTypes.string, theme: PropTypes.string,
isMasterDetail: PropTypes.bool, isMasterDetail: PropTypes.bool
appStart: PropTypes.func,
toggleServerDropdown: PropTypes.func,
selectServerRequest: PropTypes.func,
initAdd: PropTypes.func
}; };
constructor(props) { constructor(props) {
@ -89,13 +85,13 @@ class ServerDropdown extends Component {
} }
close = () => { close = () => {
const { toggleServerDropdown } = this.props; const { dispatch } = this.props;
Animated.timing(this.animatedValue, { Animated.timing(this.animatedValue, {
toValue: 0, toValue: 0,
duration: ANIMATION_DURATION, duration: ANIMATION_DURATION,
easing: Easing.inOut(Easing.quad), easing: Easing.inOut(Easing.quad),
useNativeDriver: true useNativeDriver: true
}).start(() => toggleServerDropdown()); }).start(() => dispatch(toggleServerDropdown()));
}; };
createWorkspace = async () => { createWorkspace = async () => {
@ -108,10 +104,10 @@ class ServerDropdown extends Component {
}; };
navToNewServer = previousServer => { navToNewServer = previousServer => {
const { appStart, initAdd } = this.props; const { dispatch } = this.props;
batch(() => { batch(() => {
appStart({ root: ROOT_OUTSIDE }); dispatch(appStart({ root: ROOT_OUTSIDE }));
initAdd(previousServer); dispatch(serverInitAdd(previousServer));
}); });
}; };
@ -125,7 +121,7 @@ class ServerDropdown extends Component {
}; };
select = async (server, version) => { select = async (server, version) => {
const { server: currentServer, selectServerRequest, isMasterDetail } = this.props; const { server: currentServer, dispatch, isMasterDetail } = this.props;
this.close(); this.close();
if (currentServer !== server) { if (currentServer !== server) {
logEvent(events.RL_CHANGE_SERVER); logEvent(events.RL_CHANGE_SERVER);
@ -142,7 +138,7 @@ class ServerDropdown extends Component {
}, ANIMATION_DURATION); }, ANIMATION_DURATION);
} else { } else {
await localAuthenticate(server); await localAuthenticate(server);
selectServerRequest(server, version); dispatch(selectServerRequest(server, version, true, true));
} }
} }
}; };
@ -263,11 +259,4 @@ const mapStateToProps = state => ({
isMasterDetail: state.app.isMasterDetail isMasterDetail: state.app.isMasterDetail
}); });
const mapDispatchToProps = dispatch => ({ export default connect(mapStateToProps)(withSafeAreaInsets(withTheme(ServerDropdown)));
toggleServerDropdown: () => dispatch(toggleServerDropdownAction()),
selectServerRequest: (server, version) => dispatch(selectServerRequestAction(server, version, true, true)),
appStart: params => dispatch(appStartAction(params)),
initAdd: previousServer => dispatch(serverInitAddAction(previousServer))
});
export default connect(mapStateToProps, mapDispatchToProps)(withSafeAreaInsets(withTheme(ServerDropdown)));

View File

@ -12,19 +12,13 @@ import RocketChat from '../../lib/rocketchat';
import RoomItem, { ROW_HEIGHT, ROW_HEIGHT_CONDENSED } from '../../presentation/RoomItem'; import RoomItem, { ROW_HEIGHT, ROW_HEIGHT_CONDENSED } from '../../presentation/RoomItem';
import log, { logEvent, events } from '../../utils/log'; import log, { logEvent, events } from '../../utils/log';
import I18n from '../../i18n'; import I18n from '../../i18n';
import { import { closeSearchHeader, closeServerDropdown, openSearchHeader, roomsRequest } from '../../actions/rooms';
closeSearchHeader as closeSearchHeaderAction, import { appStart, ROOT_OUTSIDE } from '../../actions/app';
closeServerDropdown as closeServerDropdownAction,
openSearchHeader as openSearchHeaderAction,
roomsRequest as roomsRequestAction
} from '../../actions/rooms';
import { appStart as appStartAction, ROOT_OUTSIDE } from '../../actions/app';
import debounce from '../../utils/debounce'; import debounce from '../../utils/debounce';
import { isIOS, isTablet } from '../../utils/deviceInfo'; import { isIOS, isTablet } from '../../utils/deviceInfo';
import * as HeaderButton from '../../containers/HeaderButton'; import * as HeaderButton from '../../containers/HeaderButton';
import StatusBar from '../../containers/StatusBar'; import StatusBar from '../../containers/StatusBar';
import ActivityIndicator from '../../containers/ActivityIndicator'; import ActivityIndicator from '../../containers/ActivityIndicator';
import { selectServerRequest as selectServerRequestAction, serverInitAdd as serverInitAddAction } from '../../actions/server';
import { animateNextTransition } from '../../utils/layoutAnimation'; import { animateNextTransition } from '../../utils/layoutAnimation';
import { withTheme } from '../../theme'; import { withTheme } from '../../theme';
import { themes } from '../../constants/colors'; import { themes } from '../../constants/colors';
@ -124,11 +118,6 @@ class RoomsListView extends React.Component {
refreshing: PropTypes.bool, refreshing: PropTypes.bool,
StoreLastMessage: PropTypes.bool, StoreLastMessage: PropTypes.bool,
theme: PropTypes.string, theme: PropTypes.string,
openSearchHeader: PropTypes.func,
closeSearchHeader: PropTypes.func,
appStart: PropTypes.func,
roomsRequest: PropTypes.func,
closeServerDropdown: PropTypes.func,
useRealName: PropTypes.bool, useRealName: PropTypes.bool,
isMasterDetail: PropTypes.bool, isMasterDetail: PropTypes.bool,
rooms: PropTypes.array, rooms: PropTypes.array,
@ -169,7 +158,7 @@ class RoomsListView extends React.Component {
} }
componentDidMount() { componentDidMount() {
const { navigation, closeServerDropdown } = this.props; const { navigation, dispatch } = this.props;
this.handleHasPermission(); this.handleHasPermission();
this.mounted = true; this.mounted = true;
@ -193,7 +182,7 @@ class RoomsListView extends React.Component {
}); });
this.unsubscribeBlur = navigation.addListener('blur', () => { this.unsubscribeBlur = navigation.addListener('blur', () => {
this.animated = false; this.animated = false;
closeServerDropdown(); dispatch(closeServerDropdown());
this.cancelSearch(); this.cancelSearch();
if (this.backHandler && this.backHandler.remove) { if (this.backHandler && this.backHandler.remove) {
this.backHandler.remove(); this.backHandler.remove();
@ -553,9 +542,9 @@ class RoomsListView extends React.Component {
initSearching = () => { initSearching = () => {
logEvent(events.RL_SEARCH); logEvent(events.RL_SEARCH);
const { openSearchHeader } = this.props; const { dispatch } = this.props;
this.internalSetState({ searching: true }, () => { this.internalSetState({ searching: true }, () => {
openSearchHeader(); dispatch(openSearchHeader());
this.search(''); this.search('');
this.setHeader(); this.setHeader();
}); });
@ -563,7 +552,7 @@ class RoomsListView extends React.Component {
cancelSearch = () => { cancelSearch = () => {
const { searching } = this.state; const { searching } = this.state;
const { closeSearchHeader } = this.props; const { dispatch } = this.props;
if (!searching) { if (!searching) {
return; return;
@ -573,7 +562,7 @@ class RoomsListView extends React.Component {
this.setState({ searching: false, search: [] }, () => { this.setState({ searching: false, search: [] }, () => {
this.setHeader(); this.setHeader();
closeSearchHeader(); dispatch(closeSearchHeader());
setTimeout(() => { setTimeout(() => {
this.scrollToTop(); this.scrollToTop();
}, 200); }, 200);
@ -842,7 +831,7 @@ class RoomsListView extends React.Component {
}; };
handleCommands = ({ event }) => { handleCommands = ({ event }) => {
const { navigation, server, isMasterDetail, appStart, initAdd } = this.props; const { navigation, server, isMasterDetail, dispatch, initAdd } = this.props;
const { input } = event; const { input } = event;
if (handleCommandShowPreferences(event)) { if (handleCommandShowPreferences(event)) {
navigation.navigate('SettingsView'); navigation.navigate('SettingsView');
@ -862,7 +851,7 @@ class RoomsListView extends React.Component {
} }
} else if (handleCommandAddNewServer(event)) { } else if (handleCommandAddNewServer(event)) {
batch(() => { batch(() => {
appStart({ root: ROOT_OUTSIDE }); dispatch(appStart({ root: ROOT_OUTSIDE }));
initAdd(server); initAdd(server);
}); });
} }
@ -870,11 +859,11 @@ class RoomsListView extends React.Component {
onRefresh = () => { onRefresh = () => {
const { searching } = this.state; const { searching } = this.state;
const { roomsRequest } = this.props; const { dispatch } = this.props;
if (searching) { if (searching) {
return; return;
} }
roomsRequest({ allData: true }); dispatch(roomsRequest({ allData: true }));
}; };
onEndReached = () => { onEndReached = () => {
@ -1045,14 +1034,4 @@ const mapStateToProps = state => ({
createDiscussionPermission: state.permissions['start-discussion'] createDiscussionPermission: state.permissions['start-discussion']
}); });
const mapDispatchToProps = dispatch => ({ export default connect(mapStateToProps)(withDimensions(withTheme(withSafeAreaInsets(RoomsListView))));
openSearchHeader: () => dispatch(openSearchHeaderAction()),
closeSearchHeader: () => dispatch(closeSearchHeaderAction()),
roomsRequest: params => dispatch(roomsRequestAction(params)),
selectServerRequest: server => dispatch(selectServerRequestAction(server)),
closeServerDropdown: () => dispatch(closeServerDropdownAction()),
appStart: params => dispatch(appStartAction(params)),
initAdd: previousServer => dispatch(serverInitAddAction(previousServer))
});
export default connect(mapStateToProps, mapDispatchToProps)(withDimensions(withTheme(withSafeAreaInsets(RoomsListView))));