Greatly increased performance

This commit is contained in:
Arnaud Vergnet 2020-04-16 22:34:17 +02:00
parent 7998fa47ca
commit ef23280493
3 changed files with 109 additions and 52 deletions

View file

@ -1,11 +1,12 @@
// @flow
import * as React from 'react';
import {IconButton, List, withTheme} from 'react-native-paper';
import {List, withTheme} from 'react-native-paper';
import {FlatList, View} from "react-native";
import {stringMatchQuery} from "../../utils/Search";
import Collapsible from "react-native-collapsible";
import * as Animatable from "react-native-animatable";
import GroupListItem from "./GroupListItem";
type Props = {
item: Object,
@ -42,45 +43,27 @@ class GroupListAccordion extends React.Component<Props, State> {
return (nextProps.currentSearchString !== this.props.currentSearchString)
|| (nextSate.expanded !== this.state.expanded)
|| (nextProps.favoriteNumber !== this.props.favoriteNumber);
|| (nextProps.favoriteNumber !== this.props.favoriteNumber)
|| (nextProps.item.content.length !== this.props.item.content.length);
}
onPress = () => {
this.chevronRef.current.transitionTo({ rotate: this.state.expanded ? '0deg' : '180deg' });
this.chevronRef.current.transitionTo({rotate: this.state.expanded ? '0deg' : '180deg'});
this.setState({expanded: !this.state.expanded})
};
keyExtractor = (item: Object) => item.id.toString();
isItemFavorite(item: Object) {
return item.isFav !== undefined && item.isFav;
}
renderItem = ({item}: Object) => {
if (stringMatchQuery(item.name, this.props.currentSearchString)) {
const onPress = () => this.props.onGroupPress(item);
const onStartPress = () => this.props.onFavoritePress(item);
return (
<List.Item
title={item.name}
<GroupListItem
height={LIST_ITEM_HEIGHT}
item={item}
onPress={onPress}
left={props =>
<List.Icon
{...props}
icon={"chevron-right"}/>}
right={props =>
<IconButton
{...props}
icon={"star"}
onPress={onStartPress}
color={this.isItemFavorite(item) ? this.props.theme.colors.tetrisScore : props.color}
/>}
style={{
height: LIST_ITEM_HEIGHT,
justifyContent: 'center',
}}
/>
onStartPress={onStartPress}/>
);
} else
return null;
@ -90,16 +73,20 @@ class GroupListAccordion extends React.Component<Props, State> {
render() {
const item = this.props.item;
const accordionColor = this.state.expanded
? this.props.theme.colors.primary
: this.props.theme.colors.text;
// console.log(item.id);
return (
<View>
<List.Item
title={item.name}
expanded={this.state.expanded}
onPress={this.onPress}
style={{
height: this.props.height,
justifyContent: 'center',
}}
titleStyle={{color: accordionColor}}
left={props =>
item.id === "0"
? <List.Icon
@ -112,22 +99,30 @@ class GroupListAccordion extends React.Component<Props, State> {
ref={this.chevronRef}
{...props}
icon={"chevron-down"}
color={this.state.expanded
? this.props.theme.colors.primary
: props.color
}
useNativeDriver
/>}
/>
<Collapsible
collapsed={!this.state.expanded}
ease={"easeInOut"}
>
<FlatList
data={item.content}
extraData={this.props.currentSearchString}
renderItem={this.renderItem}
keyExtractor={this.keyExtractor}
listKey={item.id}
// Performance props, see https://reactnative.dev/docs/optimizing-flatlist-configuration
getItemLayout={this.itemLayout} // Broken with search
removeClippedSubviews={true}
/>
{this.state.expanded // Only render list if expanded for increased performance
? <FlatList
data={item.content}
extraData={this.props.currentSearchString}
renderItem={this.renderItem}
keyExtractor={this.keyExtractor}
listKey={item.id}
// Performance props, see https://reactnative.dev/docs/optimizing-flatlist-configuration
getItemLayout={this.itemLayout} // Broken with search
removeClippedSubviews={true}
/>
: null}
</Collapsible>
</View>
);

View file

@ -0,0 +1,66 @@
// @flow
import * as React from 'react';
import {IconButton, List, withTheme} from 'react-native-paper';
type Props = {
theme: Object,
onPress: Function,
onStartPress: Function,
item: Object,
height: number,
}
type State = {
isFav: boolean,
}
class GroupListItem extends React.Component<Props, State> {
colors: Object;
constructor(props) {
super(props);
this.colors = props.theme.colors;
this.state = {
isFav: (props.item.isFav !== undefined && props.item.isFav),
}
}
shouldComponentUpdate(prevProps: Props, prevState: State) {
return (prevState.isFav !== this.state.isFav);
}
onStarPress = () => {
this.setState({isFav: !this.state.isFav});
this.props.onStartPress();
}
render() {
return (
<List.Item
title={this.props.item.name}
onPress={this.props.onPress}
left={props =>
<List.Icon
{...props}
icon={"chevron-right"}/>}
right={props =>
<IconButton
{...props}
icon={"star"}
onPress={this.onStarPress}
color={this.state.isFav
? this.props.theme.colors.tetrisScore
: props.color}
/>}
style={{
height: this.props.height,
justifyContent: 'center',
}}
/>
);
}
}
export default withTheme(GroupListItem);

View file

@ -1,7 +1,7 @@
// @flow
import * as React from 'react';
import {Platform, View} from "react-native";
import {Platform} from "react-native";
import i18n from "i18n-js";
import {Searchbar, withTheme} from "react-native-paper";
import {stringMatchQuery} from "../utils/Search";
@ -206,20 +206,16 @@ class GroupSelectionScreen extends React.Component<Props, State> {
render() {
return (
<View style={{
height: '100%'
}}>
<WebSectionList
{...this.props}
createDataset={this.createDataset}
autoRefreshTime={0}
refreshOnFocus={false}
fetchUrl={GROUPS_URL}
renderItem={this.renderItem}
updateData={this.state.currentSearchString + this.state.favoriteGroups.length}
itemHeight={LIST_ITEM_HEIGHT}
/>
</View>
<WebSectionList
{...this.props}
createDataset={this.createDataset}
autoRefreshTime={0}
refreshOnFocus={false}
fetchUrl={GROUPS_URL}
renderItem={this.renderItem}
updateData={this.state.currentSearchString + this.state.favoriteGroups.length}
itemHeight={LIST_ITEM_HEIGHT}
/>
);
}
}