Chore: Migrate SelectedUsersView to Typescript (#3520)

Co-authored-by: AlexAlexandre <alexalexandrejr@gmail.com>
Co-authored-by: Diego Mello <diegolmello@gmail.com>
This commit is contained in:
Reinaldo Neto 2021-12-13 13:28:59 -03:00 committed by GitHub
parent 4ba589cfbe
commit 1ea6fe1133
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 66 additions and 51 deletions

View File

@ -46,7 +46,7 @@ interface IUserItem {
testID: string; testID: string;
onLongPress?: () => void; onLongPress?: () => void;
style?: StyleProp<ViewStyle>; style?: StyleProp<ViewStyle>;
icon?: string; icon?: string | null;
theme: string; theme: string;
} }

View File

@ -1,9 +1,11 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; 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 orderBy from 'lodash/orderBy';
import { Q } from '@nozbe/watermelondb'; import { Q } from '@nozbe/watermelondb';
import { Subscription } from 'rxjs';
import * as List from '../containers/List'; import * as List from '../containers/List';
import database from '../lib/database'; import database from '../lib/database';
@ -22,33 +24,51 @@ import { addUser as addUserAction, removeUser as removeUserAction, reset as rese
import { showErrorAlert } from '../utils/info'; import { showErrorAlert } from '../utils/info';
import SafeAreaView from '../containers/SafeAreaView'; import SafeAreaView from '../containers/SafeAreaView';
import sharedStyles from './Styles'; import sharedStyles from './Styles';
import { ChatsStackParamList } from '../stacks/types';
const ITEM_WIDTH = 250; const ITEM_WIDTH = 250;
const getItemLayout = (_, index) => ({ length: ITEM_WIDTH, offset: ITEM_WIDTH * index, index }); const getItemLayout = (_: any, index: number) => ({ length: ITEM_WIDTH, offset: ITEM_WIDTH * index, index });
class SelectedUsersView extends React.Component { interface IUser {
static propTypes = { _id: string;
baseUrl: PropTypes.string, name: string;
addUser: PropTypes.func.isRequired, fname: string;
removeUser: PropTypes.func.isRequired, search?: boolean;
reset: PropTypes.func.isRequired, // username is used when is from searching
users: PropTypes.array, username?: string;
loading: PropTypes.bool, }
user: PropTypes.shape({ interface ISelectedUsersViewState {
id: PropTypes.string, maxUsers?: number;
token: PropTypes.string, search: IUser[];
username: PropTypes.string, chats: IUser[];
name: PropTypes.string }
}),
navigation: PropTypes.object, interface ISelectedUsersViewProps {
route: PropTypes.object, navigation: StackNavigationProp<ChatsStackParamList, 'SelectedUsersView'>;
theme: PropTypes.string route: RouteProp<ChatsStackParamList, 'SelectedUsersView'>;
baseUrl: string;
addUser(user: IUser): void;
removeUser(user: IUser): void;
reset(): void;
users: IUser[];
loading: boolean;
user: {
id: string;
token: string;
username: string;
name: string;
}; };
theme: string;
}
constructor(props) { class SelectedUsersView extends React.Component<ISelectedUsersViewProps, ISelectedUsersViewState> {
private flatlist?: FlatList;
private querySubscription?: Subscription;
constructor(props: ISelectedUsersViewProps) {
super(props); super(props);
this.init(); this.init();
this.flatlist = React.createRef();
const maxUsers = props.route.params?.maxUsers; const maxUsers = props.route.params?.maxUsers;
this.state = { this.state = {
maxUsers, maxUsers,
@ -62,7 +82,7 @@ class SelectedUsersView extends React.Component {
this.setHeader(props.route.params?.showButton); this.setHeader(props.route.params?.showButton);
} }
componentDidUpdate(prevProps) { componentDidUpdate(prevProps: ISelectedUsersViewProps) {
if (this.isGroupChat()) { if (this.isGroupChat()) {
const { users } = this.props; const { users } = this.props;
if (prevProps.users.length !== users.length) { if (prevProps.users.length !== users.length) {
@ -80,7 +100,7 @@ class SelectedUsersView extends React.Component {
} }
// showButton can be sent as route params or updated by the component // showButton can be sent as route params or updated by the component
setHeader = showButton => { setHeader = (showButton?: boolean) => {
const { navigation, route } = this.props; const { navigation, route } = this.props;
const title = route.params?.title ?? I18n.t('Select_Users'); const title = route.params?.title ?? I18n.t('Select_Users');
const buttonText = route.params?.buttonText ?? I18n.t('Next'); const buttonText = route.params?.buttonText ?? I18n.t('Next');
@ -107,7 +127,8 @@ class SelectedUsersView extends React.Component {
.query(Q.where('t', 'd')) .query(Q.where('t', 'd'))
.observeWithColumns(['room_updated_at']); .observeWithColumns(['room_updated_at']);
this.querySubscription = observable.subscribe(data => { // TODO: Refactor when migrate room
this.querySubscription = observable.subscribe((data: any) => {
const chats = orderBy(data, ['roomUpdatedAt'], ['desc']); const chats = orderBy(data, ['roomUpdatedAt'], ['desc']);
this.setState({ chats }); this.setState({ chats });
}); });
@ -116,11 +137,11 @@ class SelectedUsersView extends React.Component {
} }
}; };
onSearchChangeText(text) { onSearchChangeText(text: string) {
this.search(text); this.search(text);
} }
search = async text => { search = async (text: string) => {
const result = await RocketChat.search({ text, filterRooms: false }); const result = await RocketChat.search({ text, filterRooms: false });
this.setState({ this.setState({
search: result search: result
@ -129,15 +150,15 @@ class SelectedUsersView extends React.Component {
isGroupChat = () => { isGroupChat = () => {
const { maxUsers } = this.state; const { maxUsers } = this.state;
return maxUsers > 2; return maxUsers! > 2;
}; };
isChecked = username => { isChecked = (username: string) => {
const { users } = this.props; const { users } = this.props;
return users.findIndex(el => el.name === username) !== -1; return users.findIndex(el => el.name === username) !== -1;
}; };
toggleUser = user => { toggleUser = (user: IUser) => {
const { maxUsers } = this.state; const { maxUsers } = this.state;
const { const {
addUser, addUser,
@ -163,29 +184,29 @@ class SelectedUsersView extends React.Component {
} }
}; };
_onPressItem = (id, item = {}) => { _onPressItem = (id: string, item = {} as IUser) => {
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 {
this.toggleUser({ _id: item._id, name: item.name, fname: item.fname }); this.toggleUser({ _id: item._id, name: item.name, fname: item.fname });
} }
}; };
_onPressSelectedItem = item => this.toggleUser(item); _onPressSelectedItem = (item: IUser) => this.toggleUser(item);
renderHeader = () => { renderHeader = () => {
const { theme } = this.props; const { theme } = this.props;
return ( return (
<View style={{ backgroundColor: themes[theme].backgroundColor }}> <View style={{ backgroundColor: themes[theme].backgroundColor }}>
<SearchBox onChangeText={text => this.onSearchChangeText(text)} testID='select-users-view-search' /> <SearchBox onChangeText={(text: string) => this.onSearchChangeText(text)} testID='select-users-view-search' />
{this.renderSelected()} {this.renderSelected()}
</View> </View>
); );
}; };
setFlatListRef = ref => (this.flatlist = ref); setFlatListRef = (ref: FlatList) => (this.flatlist = ref);
onContentSizeChange = () => this.flatlist.scrollToEnd({ animated: true }); onContentSizeChange = () => this.flatlist?.scrollToEnd({ animated: true });
renderSelected = () => { renderSelected = () => {
const { users, theme } = this.props; const { users, theme } = this.props;
@ -204,35 +225,32 @@ class SelectedUsersView extends React.Component {
style={[sharedStyles.separatorTop, { borderColor: themes[theme].separatorColor }]} style={[sharedStyles.separatorTop, { borderColor: themes[theme].separatorColor }]}
contentContainerStyle={{ marginVertical: 5 }} contentContainerStyle={{ marginVertical: 5 }}
renderItem={this.renderSelectedItem} renderItem={this.renderSelectedItem}
enableEmptySections
keyboardShouldPersistTaps='always' keyboardShouldPersistTaps='always'
horizontal horizontal
/> />
); );
}; };
renderSelectedItem = ({ item }) => { renderSelectedItem = ({ item }: { item: IUser }) => {
const { baseUrl, user, theme } = this.props; const { theme } = this.props;
return ( return (
<UserItem <UserItem
name={item.fname} name={item.fname}
username={item.name} username={item.name}
onPress={() => this._onPressSelectedItem(item)} onPress={() => this._onPressSelectedItem(item)}
testID={`selected-user-${item.name}`} testID={`selected-user-${item.name}`}
baseUrl={baseUrl}
style={{ paddingRight: 15 }} style={{ paddingRight: 15 }}
user={user}
theme={theme} theme={theme}
/> />
); );
}; };
renderItem = ({ item, index }) => { renderItem = ({ item, index }: { item: IUser; index: number }) => {
const { search, chats } = this.state; const { search, chats } = this.state;
const { baseUrl, user, theme } = this.props; const { theme } = this.props;
const name = item.search ? item.name : item.fname; const name = item.search ? item.name : item.fname;
const username = item.search ? item.username : item.name; const username = item.search ? item.username! : item.name;
let style = { borderColor: themes[theme].separatorColor }; let style = { borderColor: themes[theme].separatorColor };
if (index === 0) { if (index === 0) {
style = { ...style, ...sharedStyles.separatorTop }; style = { ...style, ...sharedStyles.separatorTop };
@ -250,9 +268,7 @@ class SelectedUsersView extends React.Component {
onPress={() => this._onPressItem(item._id, item)} onPress={() => this._onPressItem(item._id, item)}
testID={`select-users-view-item-${item.name}`} testID={`select-users-view-item-${item.name}`}
icon={this.isChecked(username) ? 'check' : null} icon={this.isChecked(username) ? 'check' : null}
baseUrl={baseUrl}
style={style} style={style}
user={user}
theme={theme} theme={theme}
/> />
); );
@ -275,7 +291,6 @@ class SelectedUsersView extends React.Component {
ItemSeparatorComponent={List.Separator} ItemSeparatorComponent={List.Separator}
ListHeaderComponent={this.renderHeader} ListHeaderComponent={this.renderHeader}
contentContainerStyle={{ backgroundColor: themes[theme].backgroundColor }} contentContainerStyle={{ backgroundColor: themes[theme].backgroundColor }}
enableEmptySections
keyboardShouldPersistTaps='always' keyboardShouldPersistTaps='always'
/> />
); );
@ -293,16 +308,16 @@ class SelectedUsersView extends React.Component {
}; };
} }
const mapStateToProps = state => ({ const mapStateToProps = (state: any) => ({
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 => ({ const mapDispatchToProps = (dispatch: any) => ({
addUser: user => dispatch(addUserAction(user)), addUser: (user: any) => dispatch(addUserAction(user)),
removeUser: user => dispatch(removeUserAction(user)), removeUser: (user: any) => dispatch(removeUserAction(user)),
reset: () => dispatch(resetAction()) reset: () => dispatch(resetAction())
}); });