Browse Source

Improved proximo search and display performance

Arnaud Vergnet 4 years ago
parent
commit
ba893495e1
2 changed files with 83 additions and 88 deletions
  1. 40
    0
      components/Lists/ProximoListItem.js
  2. 43
    88
      screens/Proximo/ProximoListScreen.js

+ 40
- 0
components/Lists/ProximoListItem.js View File

@@ -0,0 +1,40 @@
1
+// @flow
2
+
3
+import * as React from 'react';
4
+import {Avatar, List, Text, withTheme} from 'react-native-paper';
5
+import i18n from "i18n-js";
6
+
7
+type Props = {
8
+    onPress: Function,
9
+    color: string,
10
+    item: Object,
11
+}
12
+
13
+class ProximoListItem extends React.PureComponent<Props> {
14
+
15
+    colors: Object;
16
+
17
+    constructor(props) {
18
+        super(props);
19
+        this.colors = props.theme.colors;
20
+    }
21
+
22
+    render() {
23
+        return (
24
+            <List.Item
25
+                title={this.props.item.name}
26
+                description={this.props.item.quantity + ' ' + i18n.t('proximoScreen.inStock')}
27
+                descriptionStyle={{color: this.props.color}}
28
+                onPress={this.props.onPress}
29
+                left={() => <Avatar.Image style={{backgroundColor: 'transparent'}} size={64}
30
+                                          source={{uri: this.props.item.image}}/>}
31
+                right={() =>
32
+                    <Text style={{fontWeight: "bold"}}>
33
+                        {this.props.item.price}€
34
+                    </Text>}
35
+            />
36
+        );
37
+    }
38
+}
39
+
40
+export default withTheme(ProximoListItem);

+ 43
- 88
screens/Proximo/ProximoListScreen.js View File

@@ -1,11 +1,12 @@
1 1
 // @flow
2 2
 
3 3
 import * as React from 'react';
4
-import {Image, Platform, ScrollView, View} from "react-native";
4
+import {FlatList, Image, Platform, ScrollView, View} from "react-native";
5 5
 import i18n from "i18n-js";
6 6
 import CustomModal from "../../components/Custom/CustomModal";
7
-import {Avatar, IconButton, List, RadioButton, Searchbar, Subheading, Text, Title, withTheme} from "react-native-paper";
8
-import PureFlatList from "../../components/Lists/PureFlatList";
7
+import {IconButton, RadioButton, Searchbar, Subheading, Text, Title, withTheme} from "react-native-paper";
8
+import {stringMatchQuery} from "../../utils/Search";
9
+import ProximoListItem from "../../components/Lists/ProximoListItem";
9 10
 
10 11
 function sortPrice(a, b) {
11 12
     return a.price - b.price;
@@ -39,7 +40,7 @@ type Props = {
39 40
 type State = {
40 41
     currentSortMode: number,
41 42
     modalCurrentDisplayItem: React.Node,
42
-    currentlyDisplayedData: Array<Object>,
43
+    currentSearchString: string,
43 44
 };
44 45
 
45 46
 /**
@@ -48,30 +49,21 @@ type State = {
48 49
 class ProximoListScreen extends React.Component<Props, State> {
49 50
 
50 51
     modalRef: Object;
51
-    originalData: Array<Object>;
52
+    listData: Array<Object>;
52 53
     shouldFocusSearchBar: boolean;
53 54
 
54
-    onSearchStringChange: Function;
55
-    onSortMenuPress: Function;
56
-    renderItem: Function;
57
-    onModalRef: Function;
58
-
59 55
     colors: Object;
60 56
 
61 57
     constructor(props) {
62 58
         super(props);
63
-        this.originalData = this.props.route.params['data']['data'];
59
+        this.listData = this.props.route.params['data']['data'];
64 60
         this.shouldFocusSearchBar = this.props.route.params['shouldFocusSearchBar'];
65 61
         this.state = {
66
-            currentlyDisplayedData: this.originalData.sort(sortName),
62
+            currentSearchString: '',
67 63
             currentSortMode: 3,
68 64
             modalCurrentDisplayItem: null,
69 65
         };
70 66
 
71
-        this.onSearchStringChange = this.onSearchStringChange.bind(this);
72
-        this.onSortMenuPress = this.onSortMenuPress.bind(this);
73
-        this.renderItem = this.renderItem.bind(this);
74
-        this.onModalRef = this.onModalRef.bind(this);
75 67
         this.colors = props.theme.colors;
76 68
     }
77 69
 
@@ -80,11 +72,9 @@ class ProximoListScreen extends React.Component<Props, State> {
80 72
      * Creates the header content
81 73
      */
82 74
     componentDidMount() {
83
-        const button = this.getSortMenuButton.bind(this);
84
-        const title = this.getSearchBar.bind(this);
85 75
         this.props.navigation.setOptions({
86
-            headerRight: button,
87
-            headerTitle: title,
76
+            headerRight: this.getSortMenuButton,
77
+            headerTitle: this.getSearchBar,
88 78
             headerBackTitleVisible: false,
89 79
             headerTitleContainerStyle: Platform.OS === 'ios' ?
90 80
                 {marginHorizontal: 0, width: '70%'} :
@@ -97,21 +87,21 @@ class ProximoListScreen extends React.Component<Props, State> {
97 87
      *
98 88
      * @return {*}
99 89
      */
100
-    getSearchBar() {
90
+    getSearchBar = () => {
101 91
         return (
102 92
             <Searchbar
103 93
                 placeholder={i18n.t('proximoScreen.search')}
104 94
                 onChangeText={this.onSearchStringChange}
105 95
             />
106 96
         );
107
-    }
97
+    };
108 98
 
109 99
     /**
110 100
      * Gets the sort menu header button
111 101
      *
112 102
      * @return {*}
113 103
      */
114
-    getSortMenuButton() {
104
+    getSortMenuButton = () => {
115 105
         return (
116 106
             <IconButton
117 107
                 icon="sort"
@@ -120,20 +110,20 @@ class ProximoListScreen extends React.Component<Props, State> {
120 110
                 onPress={this.onSortMenuPress}
121 111
             />
122 112
         );
123
-    }
113
+    };
124 114
 
125 115
     /**
126 116
      * Callback used when clicking on the sort menu button.
127 117
      * It will open the modal to show a sort selection
128 118
      */
129
-    onSortMenuPress() {
119
+    onSortMenuPress = () => {
130 120
         this.setState({
131 121
             modalCurrentDisplayItem: this.getModalSortMenu()
132 122
         });
133 123
         if (this.modalRef) {
134 124
             this.modalRef.open();
135 125
         }
136
-    }
126
+    };
137 127
 
138 128
     /**
139 129
      * Sets the current sort mode.
@@ -144,19 +134,18 @@ class ProximoListScreen extends React.Component<Props, State> {
144 134
         this.setState({
145 135
             currentSortMode: mode,
146 136
         });
147
-        let data = this.state.currentlyDisplayedData;
148 137
         switch (mode) {
149 138
             case 1:
150
-                data.sort(sortPrice);
139
+                this.listData.sort(sortPrice);
151 140
                 break;
152 141
             case 2:
153
-                data.sort(sortPriceReverse);
142
+                this.listData.sort(sortPriceReverse);
154 143
                 break;
155 144
             case 3:
156
-                data.sort(sortName);
145
+                this.listData.sort(sortName);
157 146
                 break;
158 147
             case 4:
159
-                data.sort(sortNameReverse);
148
+                this.listData.sort(sortNameReverse);
160 149
                 break;
161 150
         }
162 151
         if (this.modalRef && mode !== this.state.currentSortMode) {
@@ -182,45 +171,13 @@ class ProximoListScreen extends React.Component<Props, State> {
182 171
     }
183 172
 
184 173
     /**
185
-     * Sanitizes the given string to improve search performance
186
-     *
187
-     * @param str The string to sanitize
188
-     * @return {string} The sanitized string
189
-     */
190
-    sanitizeString(str: string): string {
191
-        return str.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
192
-    }
193
-
194
-    /**
195
-     * Returns only articles whose name contains the given string.
196
-     * Case and accents insensitive.
197
-     *
198
-     * @param str The string used to filter article names
199
-     * @returns {[]}
200
-     */
201
-    filterData(str: string) {
202
-        let filteredData = [];
203
-        const testStr = this.sanitizeString(str);
204
-        const articles = this.originalData;
205
-        for (const article of articles) {
206
-            const name = this.sanitizeString(article.name);
207
-            if (name.includes(testStr)) {
208
-                filteredData.push(article)
209
-            }
210
-        }
211
-        return filteredData;
212
-    }
213
-
214
-    /**
215 174
      * Callback used when the search changes
216 175
      *
217 176
      * @param str The new search string
218 177
      */
219
-    onSearchStringChange(str: string) {
220
-        this.setState({
221
-            currentlyDisplayedData: this.filterData(str)
222
-        })
223
-    }
178
+    onSearchStringChange = (str: string) => {
179
+        this.setState({currentSearchString: str})
180
+    };
224 181
 
225 182
     /**
226 183
      * Gets the modal content depending on the given article
@@ -333,23 +290,20 @@ class ProximoListScreen extends React.Component<Props, State> {
333 290
      * @param item The article to render
334 291
      * @return {*}
335 292
      */
336
-    renderItem({item}: Object) {
337
-        const onPress = this.onListItemPress.bind(this, item);
338
-        return (
339
-            <List.Item
340
-                title={item.name}
341
-                description={item.quantity + ' ' + i18n.t('proximoScreen.inStock')}
342
-                descriptionStyle={{color: this.getStockColor(parseInt(item.quantity))}}
343
-                onPress={onPress}
344
-                left={() => <Avatar.Image style={{backgroundColor: 'transparent'}} size={64}
345
-                                          source={{uri: item.image}}/>}
346
-                right={() =>
347
-                    <Text style={{fontWeight: "bold"}}>
348
-                        {item.price}€
349
-                    </Text>}
350
-            />
351
-        );
352
-    }
293
+    renderItem = ({item}: Object) => {
294
+        if (stringMatchQuery(item.name, this.state.currentSearchString)) {
295
+            const onPress = this.onListItemPress.bind(this, item);
296
+            const color = this.getStockColor(parseInt(item.quantity));
297
+            return (
298
+                <ProximoListItem
299
+                    item={item}
300
+                    onPress={onPress}
301
+                    color={color}
302
+                />
303
+            );
304
+        } else
305
+            return null;
306
+    };
353 307
 
354 308
     /**
355 309
      * Extracts a key for the given article
@@ -366,9 +320,9 @@ class ProximoListScreen extends React.Component<Props, State> {
366 320
      *
367 321
      * @param ref
368 322
      */
369
-    onModalRef(ref: Object) {
323
+    onModalRef = (ref: Object) => {
370 324
         this.modalRef = ref;
371
-    }
325
+    };
372 326
 
373 327
     render() {
374 328
         return (
@@ -378,11 +332,12 @@ class ProximoListScreen extends React.Component<Props, State> {
378 332
                 <CustomModal onRef={this.onModalRef}>
379 333
                     {this.state.modalCurrentDisplayItem}
380 334
                 </CustomModal>
381
-                <PureFlatList
382
-                    data={this.state.currentlyDisplayedData}
335
+                {/*$FlowFixMe*/}
336
+                <FlatList
337
+                    data={this.listData}
338
+                    extraData={this.state.currentSearchString + this.state.currentSortMode}
383 339
                     keyExtractor={this.keyExtractor}
384 340
                     renderItem={this.renderItem}
385
-                    updateData={this.state.currentSortMode}
386 341
                 />
387 342
             </View>
388 343
         );

Loading…
Cancel
Save