|
@@ -18,8 +18,8 @@
|
18
|
18
|
*/
|
19
|
19
|
|
20
|
20
|
import * as React from 'react';
|
21
|
|
-import { List, withTheme } from 'react-native-paper';
|
22
|
|
-import { FlatList, StyleSheet, View } from 'react-native';
|
|
21
|
+import { List, useTheme } from 'react-native-paper';
|
|
22
|
+import { FlatList, StyleSheet } from 'react-native';
|
23
|
23
|
import GroupListItem from './GroupListItem';
|
24
|
24
|
import AnimatedAccordion from '../../Animations/AnimatedAccordion';
|
25
|
25
|
import type {
|
|
@@ -34,7 +34,6 @@ type PropsType = {
|
34
|
34
|
onGroupPress: (data: PlanexGroupType) => void;
|
35
|
35
|
onFavoritePress: (data: PlanexGroupType) => void;
|
36
|
36
|
currentSearchString: string;
|
37
|
|
- theme: ReactNativePaper.Theme;
|
38
|
37
|
};
|
39
|
38
|
|
40
|
39
|
const LIST_ITEM_HEIGHT = 64;
|
|
@@ -49,36 +48,22 @@ const styles = StyleSheet.create({
|
49
|
48
|
},
|
50
|
49
|
});
|
51
|
50
|
|
52
|
|
-class GroupListAccordion extends React.Component<PropsType> {
|
53
|
|
- shouldComponentUpdate(nextProps: PropsType): boolean {
|
54
|
|
- const { props } = this;
|
55
|
|
- return (
|
56
|
|
- nextProps.currentSearchString !== props.currentSearchString ||
|
57
|
|
- nextProps.favorites.length !== props.favorites.length ||
|
58
|
|
- nextProps.item.content.length !== props.item.content.length
|
59
|
|
- );
|
60
|
|
- }
|
|
51
|
+function GroupListAccordion(props: PropsType) {
|
|
52
|
+ const theme = useTheme();
|
61
|
53
|
|
62
|
|
- getRenderItem = ({ item }: { item: PlanexGroupType }) => {
|
63
|
|
- const { props } = this;
|
64
|
|
- const onPress = () => {
|
65
|
|
- props.onGroupPress(item);
|
66
|
|
- };
|
67
|
|
- const onStarPress = () => {
|
68
|
|
- props.onFavoritePress(item);
|
69
|
|
- };
|
|
54
|
+ const getRenderItem = ({ item }: { item: PlanexGroupType }) => {
|
70
|
55
|
return (
|
71
|
56
|
<GroupListItem
|
72
|
57
|
height={LIST_ITEM_HEIGHT}
|
73
|
58
|
item={item}
|
74
|
|
- favorites={props.favorites}
|
75
|
|
- onPress={onPress}
|
76
|
|
- onStarPress={onStarPress}
|
|
59
|
+ isFav={props.favorites.some((f) => f.id === item.id)}
|
|
60
|
+ onPress={() => props.onGroupPress(item)}
|
|
61
|
+ onStarPress={() => props.onFavoritePress(item)}
|
77
|
62
|
/>
|
78
|
63
|
);
|
79
|
64
|
};
|
80
|
65
|
|
81
|
|
- itemLayout = (
|
|
66
|
+ const itemLayout = (
|
82
|
67
|
_data: Array<PlanexGroupType> | null | undefined,
|
83
|
68
|
index: number
|
84
|
69
|
): { length: number; offset: number; index: number } => ({
|
|
@@ -87,57 +72,58 @@ class GroupListAccordion extends React.Component<PropsType> {
|
87
|
72
|
index,
|
88
|
73
|
});
|
89
|
74
|
|
90
|
|
- keyExtractor = (item: PlanexGroupType): string => item.id.toString();
|
|
75
|
+ const keyExtractor = (item: PlanexGroupType): string => item.id.toString();
|
91
|
76
|
|
92
|
|
- render() {
|
93
|
|
- const { props } = this;
|
94
|
|
- const { item } = this.props;
|
95
|
|
- var isFavorite = item.id === 0;
|
96
|
|
- var isEmptyFavorite = isFavorite && props.favorites.length === 0;
|
97
|
|
- return (
|
98
|
|
- <View>
|
99
|
|
- <AnimatedAccordion
|
100
|
|
- title={
|
101
|
|
- isEmptyFavorite
|
102
|
|
- ? i18n.t('screens.planex.favorites.empty.title')
|
103
|
|
- : item.name.replace(REPLACE_REGEX, ' ')
|
104
|
|
- }
|
105
|
|
- subtitle={
|
106
|
|
- isEmptyFavorite
|
107
|
|
- ? i18n.t('screens.planex.favorites.empty.subtitle')
|
108
|
|
- : undefined
|
109
|
|
- }
|
110
|
|
- style={styles.container}
|
111
|
|
- left={(iconProps) =>
|
112
|
|
- isFavorite ? (
|
113
|
|
- <List.Icon
|
114
|
|
- style={iconProps.style}
|
115
|
|
- icon={'star'}
|
116
|
|
- color={props.theme.colors.tetrisScore}
|
117
|
|
- />
|
118
|
|
- ) : undefined
|
119
|
|
- }
|
120
|
|
- unmountWhenCollapsed={!isFavorite} // Only render list if expanded for increased performance
|
121
|
|
- opened={
|
122
|
|
- props.currentSearchString.length >= MIN_SEARCH_SIZE_EXPAND ||
|
123
|
|
- (isFavorite && !isEmptyFavorite)
|
124
|
|
- }
|
125
|
|
- enabled={!isEmptyFavorite}
|
126
|
|
- >
|
127
|
|
- <FlatList
|
128
|
|
- data={props.item.content}
|
129
|
|
- extraData={props.currentSearchString + props.favorites.length}
|
130
|
|
- renderItem={this.getRenderItem}
|
131
|
|
- keyExtractor={this.keyExtractor}
|
132
|
|
- listKey={item.id.toString()}
|
133
|
|
- // Performance props, see https://reactnative.dev/docs/optimizing-flatlist-configuration
|
134
|
|
- getItemLayout={this.itemLayout}
|
135
|
|
- removeClippedSubviews
|
|
77
|
+ var isFavorite = props.item.id === 0;
|
|
78
|
+ var isEmptyFavorite = isFavorite && props.favorites.length === 0;
|
|
79
|
+
|
|
80
|
+ return (
|
|
81
|
+ <AnimatedAccordion
|
|
82
|
+ title={
|
|
83
|
+ isEmptyFavorite
|
|
84
|
+ ? i18n.t('screens.planex.favorites.empty.title')
|
|
85
|
+ : props.item.name.replace(REPLACE_REGEX, ' ')
|
|
86
|
+ }
|
|
87
|
+ subtitle={
|
|
88
|
+ isEmptyFavorite
|
|
89
|
+ ? i18n.t('screens.planex.favorites.empty.subtitle')
|
|
90
|
+ : undefined
|
|
91
|
+ }
|
|
92
|
+ style={styles.container}
|
|
93
|
+ left={(iconProps) =>
|
|
94
|
+ isFavorite ? (
|
|
95
|
+ <List.Icon
|
|
96
|
+ style={iconProps.style}
|
|
97
|
+ icon={'star'}
|
|
98
|
+ color={theme.colors.tetrisScore}
|
136
|
99
|
/>
|
137
|
|
- </AnimatedAccordion>
|
138
|
|
- </View>
|
139
|
|
- );
|
140
|
|
- }
|
|
100
|
+ ) : undefined
|
|
101
|
+ }
|
|
102
|
+ unmountWhenCollapsed={!isFavorite} // Only render list if expanded for increased performance
|
|
103
|
+ opened={
|
|
104
|
+ props.currentSearchString.length >= MIN_SEARCH_SIZE_EXPAND ||
|
|
105
|
+ (isFavorite && !isEmptyFavorite)
|
|
106
|
+ }
|
|
107
|
+ enabled={!isEmptyFavorite}
|
|
108
|
+ >
|
|
109
|
+ <FlatList
|
|
110
|
+ data={props.item.content}
|
|
111
|
+ extraData={props.currentSearchString + props.favorites.length}
|
|
112
|
+ renderItem={getRenderItem}
|
|
113
|
+ keyExtractor={keyExtractor}
|
|
114
|
+ listKey={props.item.id.toString()}
|
|
115
|
+ // Performance props, see https://reactnative.dev/docs/optimizing-flatlist-configuration
|
|
116
|
+ getItemLayout={itemLayout}
|
|
117
|
+ removeClippedSubviews={true}
|
|
118
|
+ />
|
|
119
|
+ </AnimatedAccordion>
|
|
120
|
+ );
|
141
|
121
|
}
|
142
|
122
|
|
143
|
|
-export default withTheme(GroupListAccordion);
|
|
123
|
+const propsEqual = (pp: PropsType, np: PropsType) =>
|
|
124
|
+ pp.currentSearchString === np.currentSearchString &&
|
|
125
|
+ pp.favorites.length === np.favorites.length &&
|
|
126
|
+ pp.item.content.length === np.item.content.length &&
|
|
127
|
+ pp.onFavoritePress === np.onFavoritePress;
|
|
128
|
+
|
|
129
|
+export default React.memo(GroupListAccordion, propsEqual);
|