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;
onLongPress?: () => void;
style?: StyleProp<ViewStyle>;
icon?: string;
icon?: string | null;
theme: string;
}

View File

@ -1,9 +1,11 @@
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 { connect } from 'react-redux';
import orderBy from 'lodash/orderBy';
import { Q } from '@nozbe/watermelondb';
import { Subscription } from 'rxjs';
import * as List from '../containers/List';
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 SafeAreaView from '../containers/SafeAreaView';
import sharedStyles from './Styles';
import { ChatsStackParamList } from '../stacks/types';
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 {
static propTypes = {
baseUrl: PropTypes.string,
addUser: PropTypes.func.isRequired,
removeUser: PropTypes.func.isRequired,
reset: PropTypes.func.isRequired,
users: PropTypes.array,
loading: PropTypes.bool,
user: PropTypes.shape({
id: PropTypes.string,
token: PropTypes.string,
username: PropTypes.string,
name: PropTypes.string
}),
navigation: PropTypes.object,
route: PropTypes.object,
theme: PropTypes.string
interface IUser {
_id: string;
name: string;
fname: string;
search?: boolean;
// username is used when is from searching
username?: string;
}
interface ISelectedUsersViewState {
maxUsers?: number;
search: IUser[];
chats: IUser[];
}
interface ISelectedUsersViewProps {
navigation: StackNavigationProp<ChatsStackParamList, 'SelectedUsersView'>;
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);
this.init();
this.flatlist = React.createRef();
const maxUsers = props.route.params?.maxUsers;
this.state = {
maxUsers,
@ -62,7 +82,7 @@ class SelectedUsersView extends React.Component {
this.setHeader(props.route.params?.showButton);
}
componentDidUpdate(prevProps) {
componentDidUpdate(prevProps: ISelectedUsersViewProps) {
if (this.isGroupChat()) {
const { users } = this.props;
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
setHeader = showButton => {
setHeader = (showButton?: boolean) => {
const { navigation, route } = this.props;
const title = route.params?.title ?? I18n.t('Select_Users');
const buttonText = route.params?.buttonText ?? I18n.t('Next');
@ -107,7 +127,8 @@ class SelectedUsersView extends React.Component {
.query(Q.where('t', 'd'))
.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']);
this.setState({ chats });
});
@ -116,11 +137,11 @@ class SelectedUsersView extends React.Component {
}
};
onSearchChangeText(text) {
onSearchChangeText(text: string) {
this.search(text);
}
search = async text => {
search = async (text: string) => {
const result = await RocketChat.search({ text, filterRooms: false });
this.setState({
search: result
@ -129,15 +150,15 @@ class SelectedUsersView extends React.Component {
isGroupChat = () => {
const { maxUsers } = this.state;
return maxUsers > 2;
return maxUsers! > 2;
};
isChecked = username => {
isChecked = (username: string) => {
const { users } = this.props;
return users.findIndex(el => el.name === username) !== -1;
};
toggleUser = user => {
toggleUser = (user: IUser) => {
const { maxUsers } = this.state;
const {
addUser,
@ -163,29 +184,29 @@ class SelectedUsersView extends React.Component {
}
};
_onPressItem = (id, item = {}) => {
_onPressItem = (id: string, item = {} as IUser) => {
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 {
this.toggleUser({ _id: item._id, name: item.name, fname: item.fname });
}
};
_onPressSelectedItem = item => this.toggleUser(item);
_onPressSelectedItem = (item: IUser) => this.toggleUser(item);
renderHeader = () => {
const { theme } = this.props;
return (
<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()}
</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 = () => {
const { users, theme } = this.props;
@ -204,35 +225,32 @@ class SelectedUsersView extends React.Component {
style={[sharedStyles.separatorTop, { borderColor: themes[theme].separatorColor }]}
contentContainerStyle={{ marginVertical: 5 }}
renderItem={this.renderSelectedItem}
enableEmptySections
keyboardShouldPersistTaps='always'
horizontal
/>
);
};
renderSelectedItem = ({ item }) => {
const { baseUrl, user, theme } = this.props;
renderSelectedItem = ({ item }: { item: IUser }) => {
const { theme } = this.props;
return (
<UserItem
name={item.fname}
username={item.name}
onPress={() => this._onPressSelectedItem(item)}
testID={`selected-user-${item.name}`}
baseUrl={baseUrl}
style={{ paddingRight: 15 }}
user={user}
theme={theme}
/>
);
};
renderItem = ({ item, index }) => {
renderItem = ({ item, index }: { item: IUser; index: number }) => {
const { search, chats } = this.state;
const { baseUrl, user, theme } = this.props;
const { theme } = this.props;
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 };
if (index === 0) {
style = { ...style, ...sharedStyles.separatorTop };
@ -250,9 +268,7 @@ class SelectedUsersView extends React.Component {
onPress={() => this._onPressItem(item._id, item)}
testID={`select-users-view-item-${item.name}`}
icon={this.isChecked(username) ? 'check' : null}
baseUrl={baseUrl}
style={style}
user={user}
theme={theme}
/>
);
@ -275,7 +291,6 @@ class SelectedUsersView extends React.Component {
ItemSeparatorComponent={List.Separator}
ListHeaderComponent={this.renderHeader}
contentContainerStyle={{ backgroundColor: themes[theme].backgroundColor }}
enableEmptySections
keyboardShouldPersistTaps='always'
/>
);
@ -293,16 +308,16 @@ class SelectedUsersView extends React.Component {
};
}
const mapStateToProps = state => ({
const mapStateToProps = (state: any) => ({
baseUrl: state.server.server,
users: state.selectedUsers.users,
loading: state.selectedUsers.loading,
user: getUserSelector(state)
});
const mapDispatchToProps = dispatch => ({
addUser: user => dispatch(addUserAction(user)),
removeUser: user => dispatch(removeUserAction(user)),
const mapDispatchToProps = (dispatch: any) => ({
addUser: (user: any) => dispatch(addUserAction(user)),
removeUser: (user: any) => dispatch(removeUserAction(user)),
reset: () => dispatch(resetAction())
});