Browse Source

Improve planex group favorite handling

Arnaud Vergnet 3 years ago
parent
commit
327488a470

+ 2
- 2
android/app/build.gradle View File

@@ -136,8 +136,8 @@ android {
136 136
         applicationId 'fr.amicaleinsat.application'
137 137
         minSdkVersion rootProject.ext.minSdkVersion
138 138
         targetSdkVersion rootProject.ext.targetSdkVersion
139
-        versionCode 32
140
-        versionName "3.1.4"
139
+        versionCode 34
140
+        versionName "4.0.1"
141 141
         missingDimensionStrategy 'react-native-camera', 'general'
142 142
     }
143 143
     splits {

+ 8
- 6
src/components/Lists/PlanexGroups/GroupListAccordion.js View File

@@ -14,22 +14,23 @@ import type {CustomThemeType} from '../../../managers/ThemeManager';
14 14
 
15 15
 type PropsType = {
16 16
   item: PlanexGroupCategoryType,
17
+  favorites: Array<PlanexGroupType>,
17 18
   onGroupPress: (PlanexGroupType) => void,
18 19
   onFavoritePress: (PlanexGroupType) => void,
19 20
   currentSearchString: string,
20
-  favoriteNumber: number,
21 21
   height: number,
22 22
   theme: CustomThemeType,
23 23
 };
24 24
 
25 25
 const LIST_ITEM_HEIGHT = 64;
26
+const REPLACE_REGEX = /_/g;
26 27
 
27 28
 class GroupListAccordion extends React.Component<PropsType> {
28 29
   shouldComponentUpdate(nextProps: PropsType): boolean {
29 30
     const {props} = this;
30 31
     return (
31 32
       nextProps.currentSearchString !== props.currentSearchString ||
32
-      nextProps.favoriteNumber !== props.favoriteNumber ||
33
+      nextProps.favorites.length !== props.favorites.length ||
33 34
       nextProps.item.content.length !== props.item.content.length
34 35
     );
35 36
   }
@@ -46,6 +47,7 @@ class GroupListAccordion extends React.Component<PropsType> {
46 47
       <GroupListItem
47 48
         height={LIST_ITEM_HEIGHT}
48 49
         item={item}
50
+        favorites={props.favorites}
49 51
         onPress={onPress}
50 52
         onStarPress={onStarPress}
51 53
       />
@@ -80,7 +82,7 @@ class GroupListAccordion extends React.Component<PropsType> {
80 82
     return (
81 83
       <View>
82 84
         <AnimatedAccordion
83
-          title={item.name}
85
+          title={item.name.replace(REPLACE_REGEX, ' ')}
84 86
           style={{
85 87
             height: props.height,
86 88
             justifyContent: 'center',
@@ -94,11 +96,11 @@ class GroupListAccordion extends React.Component<PropsType> {
94 96
               />
95 97
             ) : null
96 98
           }
97
-          unmountWhenCollapsed // Only render list if expanded for increased performance
98
-          opened={props.item.id === 0 || props.currentSearchString.length > 0}>
99
+          unmountWhenCollapsed={item.id !== 0} // Only render list if expanded for increased performance
100
+          opened={props.currentSearchString.length > 0}>
99 101
           <FlatList
100 102
             data={this.getData()}
101
-            extraData={props.currentSearchString}
103
+            extraData={props.currentSearchString + props.favorites.length}
102 104
             renderItem={this.getRenderItem}
103 105
             keyExtractor={this.keyExtractor}
104 106
             listKey={item.id.toString()}

+ 25
- 21
src/components/Lists/PlanexGroups/GroupListItem.js View File

@@ -10,40 +10,44 @@ type PropsType = {
10 10
   onPress: () => void,
11 11
   onStarPress: () => void,
12 12
   item: PlanexGroupType,
13
+  favorites: Array<PlanexGroupType>,
13 14
   height: number,
14 15
 };
15 16
 
16
-type StateType = {
17
-  isFav: boolean,
18
-};
17
+const REPLACE_REGEX = /_/g;
18
+
19
+class GroupListItem extends React.Component<PropsType> {
20
+  isFav: boolean;
19 21
 
20
-class GroupListItem extends React.Component<PropsType, StateType> {
21 22
   constructor(props: PropsType) {
22 23
     super(props);
23
-    this.state = {
24
-      isFav: props.item.isFav !== undefined && props.item.isFav,
25
-    };
24
+    this.isFav = this.isGroupInFavorites(props.favorites);
26 25
   }
27 26
 
28
-  shouldComponentUpdate(prevProps: PropsType, prevState: StateType): boolean {
29
-    const {isFav} = this.state;
30
-    return prevState.isFav !== isFav;
27
+  shouldComponentUpdate(nextProps: PropsType): boolean {
28
+    const {favorites} = this.props;
29
+    const favChanged = favorites.length !== nextProps.favorites.length;
30
+    let newFavState = this.isFav;
31
+    if (favChanged) newFavState = this.isGroupInFavorites(nextProps.favorites);
32
+    const shouldUpdate = this.isFav !== newFavState;
33
+    this.isFav = newFavState;
34
+    return shouldUpdate;
31 35
   }
32 36
 
33
-  onStarPress = () => {
34
-    const {props} = this;
35
-    this.setState((prevState: StateType): StateType => ({
36
-      isFav: !prevState.isFav,
37
-    }));
38
-    props.onStarPress();
39
-  };
37
+  isGroupInFavorites(favorites: Array<PlanexGroupType>): boolean {
38
+    const {item} = this.props;
39
+    for (let i = 0; i < favorites.length; i += 1) {
40
+      if (favorites[i].id === item.id) return true;
41
+    }
42
+    return false;
43
+  }
40 44
 
41 45
   render(): React.Node {
42
-    const {props, state} = this;
46
+    const {props} = this;
43 47
     const {colors} = props.theme;
44 48
     return (
45 49
       <List.Item
46
-        title={props.item.name}
50
+        title={props.item.name.replace(REPLACE_REGEX, ' ')}
47 51
         onPress={props.onPress}
48 52
         left={({size}: {size: number}): React.Node => (
49 53
           <List.Icon size={size} icon="chevron-right" />
@@ -52,8 +56,8 @@ class GroupListItem extends React.Component<PropsType, StateType> {
52 56
           <IconButton
53 57
             size={size}
54 58
             icon="star"
55
-            onPress={this.onStarPress}
56
-            color={state.isFav ? colors.tetrisScore : color}
59
+            onPress={props.onStarPress}
60
+            color={this.isFav ? colors.tetrisScore : color}
57 61
           />
58 62
         )}
59 63
         style={{

+ 52
- 66
src/screens/Planex/GroupSelectionScreen.js View File

@@ -15,7 +15,6 @@ const LIST_ITEM_HEIGHT = 70;
15 15
 export type PlanexGroupType = {
16 16
   name: string,
17 17
   id: number,
18
-  isFav: boolean,
19 18
 };
20 19
 
21 20
 export type PlanexGroupCategoryType = {
@@ -43,46 +42,11 @@ function sortName(
43 42
 }
44 43
 
45 44
 const GROUPS_URL = 'http://planex.insa-toulouse.fr/wsAdeGrp.php?projectId=1';
46
-const REPLACE_REGEX = /_/g;
47 45
 
48 46
 /**
49 47
  * Class defining planex group selection screen.
50 48
  */
51 49
 class GroupSelectionScreen extends React.Component<PropsType, StateType> {
52
-  /**
53
-   * Removes the given group from the given array
54
-   *
55
-   * @param favorites The array containing favorites groups
56
-   * @param group The group to remove from the array
57
-   */
58
-  static removeGroupFromFavorites(
59
-    favorites: Array<PlanexGroupType>,
60
-    group: PlanexGroupType,
61
-  ) {
62
-    for (let i = 0; i < favorites.length; i += 1) {
63
-      if (group.id === favorites[i].id) {
64
-        favorites.splice(i, 1);
65
-        break;
66
-      }
67
-    }
68
-  }
69
-
70
-  /**
71
-   * Adds the given group to the given array
72
-   *
73
-   * @param favorites The array containing favorites groups
74
-   * @param group The group to add to the array
75
-   */
76
-  static addGroupToFavorites(
77
-    favorites: Array<PlanexGroupType>,
78
-    group: PlanexGroupType,
79
-  ) {
80
-    const favGroup = {...group};
81
-    favGroup.isFav = true;
82
-    favorites.push(favGroup);
83
-    favorites.sort(sortName);
84
-  }
85
-
86 50
   constructor(props: PropsType) {
87 51
     super(props);
88 52
     this.state = {
@@ -130,14 +94,17 @@ class GroupSelectionScreen extends React.Component<PropsType, StateType> {
130 94
    */
131 95
   getRenderItem = ({item}: {item: PlanexGroupCategoryType}): React.Node => {
132 96
     const {currentSearchString, favoriteGroups} = this.state;
133
-    if (this.shouldDisplayAccordion(item)) {
97
+    if (
98
+      this.shouldDisplayAccordion(item) ||
99
+      (item.id === 0 && item.content.length === 0)
100
+    ) {
134 101
       return (
135 102
         <GroupListAccordion
136 103
           item={item}
104
+          favorites={[...favoriteGroups]}
137 105
           onGroupPress={this.onListItemPress}
138 106
           onFavoritePress={this.onListFavoritePress}
139 107
           currentSearchString={currentSearchString}
140
-          favoriteNumber={favoriteGroups.length}
141 108
           height={LIST_ITEM_HEIGHT}
142 109
         />
143 110
       );
@@ -146,21 +113,6 @@ class GroupSelectionScreen extends React.Component<PropsType, StateType> {
146 113
   };
147 114
 
148 115
   /**
149
-   * Replaces underscore by spaces and sets the favorite state of every group in the given category
150
-   *
151
-   * @param groups The groups to format
152
-   * @return {Array<PlanexGroupType>}
153
-   */
154
-  getFormattedGroups(groups: Array<PlanexGroupType>): Array<PlanexGroupType> {
155
-    return groups.map((group: PlanexGroupType): PlanexGroupType => {
156
-      const newGroup = {...group};
157
-      newGroup.name = group.name.replace(REPLACE_REGEX, ' ');
158
-      newGroup.isFav = this.isGroupInFavorites(group);
159
-      return newGroup;
160
-    });
161
-  }
162
-
163
-  /**
164 116
    * Creates the dataset to be used in the FlatList
165 117
    *
166 118
    * @param fetchedData
@@ -231,16 +183,8 @@ class GroupSelectionScreen extends React.Component<PropsType, StateType> {
231 183
    * @param group The group to add/remove to favorites
232 184
    */
233 185
   updateGroupFavorites(group: PlanexGroupType) {
234
-    const {favoriteGroups} = this.state;
235
-    const newFavorites = [...favoriteGroups];
236
-    if (this.isGroupInFavorites(group))
237
-      GroupSelectionScreen.removeGroupFromFavorites(newFavorites, group);
238
-    else GroupSelectionScreen.addGroupToFavorites(newFavorites, group);
239
-    this.setState({favoriteGroups: newFavorites});
240
-    AsyncStorageManager.set(
241
-      AsyncStorageManager.PREFERENCES.planexFavoriteGroups.key,
242
-      newFavorites,
243
-    );
186
+    if (this.isGroupInFavorites(group)) this.removeGroupFromFavorites(group);
187
+    else this.addGroupToFavorites(group);
244 188
   }
245 189
 
246 190
   /**
@@ -276,9 +220,7 @@ class GroupSelectionScreen extends React.Component<PropsType, StateType> {
276 220
     // eslint-disable-next-line flowtype/no-weak-types
277 221
     (Object.values(fetchedData): Array<any>).forEach(
278 222
       (category: PlanexGroupCategoryType) => {
279
-        const newCat = {...category};
280
-        newCat.content = this.getFormattedGroups(category.content);
281
-        data.push(newCat);
223
+        data.push(category);
282 224
       },
283 225
     );
284 226
     data.sort(sortName);
@@ -290,6 +232,50 @@ class GroupSelectionScreen extends React.Component<PropsType, StateType> {
290 232
     return data;
291 233
   }
292 234
 
235
+  /**
236
+   * Removes the given group from the favorites
237
+   *
238
+   * @param group The group to remove from the array
239
+   */
240
+  removeGroupFromFavorites(group: PlanexGroupType) {
241
+    this.setState((prevState: StateType): {
242
+      favoriteGroups: Array<PlanexGroupType>,
243
+    } => {
244
+      const {favoriteGroups} = prevState;
245
+      for (let i = 0; i < favoriteGroups.length; i += 1) {
246
+        if (group.id === favoriteGroups[i].id) {
247
+          favoriteGroups.splice(i, 1);
248
+          break;
249
+        }
250
+      }
251
+      AsyncStorageManager.set(
252
+        AsyncStorageManager.PREFERENCES.planexFavoriteGroups.key,
253
+        favoriteGroups,
254
+      );
255
+      return {favoriteGroups};
256
+    });
257
+  }
258
+
259
+  /**
260
+   * Adds the given group to favorites
261
+   *
262
+   * @param group The group to add to the array
263
+   */
264
+  addGroupToFavorites(group: PlanexGroupType) {
265
+    this.setState((prevState: StateType): {
266
+      favoriteGroups: Array<PlanexGroupType>,
267
+    } => {
268
+      const {favoriteGroups} = prevState;
269
+      favoriteGroups.push(group);
270
+      favoriteGroups.sort(sortName);
271
+      AsyncStorageManager.set(
272
+        AsyncStorageManager.PREFERENCES.planexFavoriteGroups.key,
273
+        favoriteGroups,
274
+      );
275
+      return {favoriteGroups};
276
+    });
277
+  }
278
+
293 279
   render(): React.Node {
294 280
     const {props, state} = this;
295 281
     return (

Loading…
Cancel
Save