Improved search performance

This commit is contained in:
Arnaud Vergnet 2020-04-04 11:55:51 +02:00
parent 8f1fc3f1bd
commit c48887a0d8
5 changed files with 52 additions and 37 deletions

View file

@ -25,8 +25,10 @@ class ClubListItem extends React.PureComponent<Props> {
getCategoriesRender(categories: Array<number | null>) {
let final = [];
for (let i = 0; i < categories.length; i++) {
if (categories[i] !== null)
final.push(this.props.chipRender(this.props.categoryTranslator(categories[i])));
if (categories[i] !== null){
const category = this.props.categoryTranslator(categories[i]);
final.push(this.props.chipRender(category, this.props.item.id + ':' + category.id));
}
}
return <View style={{flexDirection: 'row'}}>{final}</View>;
}

View file

@ -262,10 +262,8 @@ function ClubStackComponent() {
name="ClubDisplayScreen"
component={ClubDisplayScreen}
options={({navigation}) => {
const openDrawer = getDrawerButton.bind(this, navigation);
return {
title: "",
headerLeft: openDrawer,
...TransitionPresets.ModalSlideFromBottomIOS,
};
}}

View file

@ -52,19 +52,26 @@ class ClubDisplayScreen extends React.Component<Props, State> {
return "";
}
getCategoriesRender(categories: Array<number|null>) {
getCategoriesRender(categories: Array<number | null>) {
let final = [];
for (let i = 0; i < categories.length; i++) {
if (categories[i] !== null)
final.push(<Chip style={{marginRight: 5}}>{this.getCategoryName(categories[i])}</Chip>);
if (categories[i] !== null) {
final.push(
<Chip
style={{marginRight: 5}}
key={i.toString()}>
{this.getCategoryName(categories[i])}
</Chip>
);
}
}
return <View style={{flexDirection: 'row', marginTop: 5}}>{final}</View>;
}
getResponsiblesRender(resp: Array<string>) {
getManagersRender(resp: Array<string>) {
let final = [];
for (let i = 0; i < resp.length; i++) {
final.push(<Paragraph>{resp[i]}</Paragraph>)
final.push(<Paragraph key={i.toString()}>{resp[i]}</Paragraph>)
}
const hasManagers = resp.length > 0;
return (
@ -120,7 +127,7 @@ class ClubDisplayScreen extends React.Component<Props, State> {
onLinkPress={openWebLink}/>
</Card.Content>
: <View/>}
{this.getResponsiblesRender(this.displayData.responsibles)}
{this.getManagersRender(this.displayData.responsibles)}
</ScrollView>
);
}

View file

@ -6,6 +6,7 @@ import {Chip, Searchbar, withTheme} from 'react-native-paper';
import AuthenticatedScreen from "../../components/Amicale/AuthenticatedScreen";
import i18n from "i18n-js";
import ClubListItem from "../../components/Lists/ClubListItem";
import {isItemInCategoryFilter, stringMatchQuery} from "../../utils/Search";
type Props = {
navigation: Object,
@ -27,7 +28,6 @@ class ClubListScreen extends React.Component<Props, State> {
colors: Object;
getRenderItem: Function;
originalData: Array<Object>;
categories: Array<Object>;
constructor(props) {
@ -69,26 +69,17 @@ class ClubListScreen extends React.Component<Props, State> {
* @param str The new search string
*/
onSearchStringChange = (str: string) => {
this.updateFilteredData(this.sanitizeString(str), null);
this.updateFilteredData(str, null);
};
/**
* Sanitizes the given string to improve search performance
*
* @param str The string to sanitize
* @return {string} The sanitized string
*/
sanitizeString(str: string): string {
return str.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
}
keyExtractor = (item: Object) => {
return item.name + item.logo;
return item.id.toString();
};
getScreen = (data: Object) => {
this.categories = data.categories;
return (
//$FlowFixMe
<FlatList
data={data.clubs}
keyExtractor={this.keyExtractor}
@ -112,7 +103,7 @@ class ClubListScreen extends React.Component<Props, State> {
if (index === -1)
newCategoriesState.push(categoryId);
else
newCategoriesState.splice(index);
newCategoriesState.splice(index,1);
}
if (filterStr !== null || categoryId !== null)
this.setState({
@ -121,21 +112,14 @@ class ClubListScreen extends React.Component<Props, State> {
})
}
isItemInCategoryFilter(categories: Array<string>) {
for (const category of categories) {
if (this.state.currentlySelectedCategories.indexOf(category) !== -1)
return true;
}
return false;
}
getChipRender = (category: Object) => {
getChipRender = (category: Object, key: string) => {
const onPress = this.onChipSelect.bind(this, category.id);
return <Chip
selected={this.isItemInCategoryFilter([category.id])}
selected={isItemInCategoryFilter(this.state.currentlySelectedCategories, [category.id])}
mode={'outlined'}
onPress={onPress}
style={{marginRight: 5, marginBottom: 5}}
key={key}
>
{category.name}
</Chip>;
@ -144,7 +128,7 @@ class ClubListScreen extends React.Component<Props, State> {
getListHeader() {
let final = [];
for (let i = 0; i < this.categories.length; i++) {
final.push(this.getChipRender(this.categories[i]));
final.push(this.getChipRender(this.categories[i], this.categories[i].id));
}
return <View style={{
justifyContent: 'space-around',
@ -163,9 +147,9 @@ class ClubListScreen extends React.Component<Props, State> {
shouldRenderItem(item) {
let shouldRender = this.state.currentlySelectedCategories.length === 0
|| this.isItemInCategoryFilter(item.category);
|| isItemInCategoryFilter(this.state.currentlySelectedCategories, item.category);
if (shouldRender)
shouldRender = this.sanitizeString(item.name).includes(this.state.currentSearchString);
shouldRender = stringMatchQuery(item.name, this.state.currentSearchString);
return shouldRender;
}

24
utils/Search.js Normal file
View file

@ -0,0 +1,24 @@
/**
* Sanitizes the given string to improve search performance
*
* @param str The string to sanitize
* @return {string} The sanitized string
*/
export function sanitizeString(str: string): string {
return str.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
}
export function stringMatchQuery(str: string, query: string) {
return sanitizeString(str).includes(sanitizeString(query));
}
export function isItemInCategoryFilter(filter: Array<string>, categories: Array<string>) {
for (const category of categories) {
if (filter.indexOf(category) !== -1)
return true;
}
return false;
}