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:
parent
4ba589cfbe
commit
1ea6fe1133
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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())
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue