Browse Source

Tried to improve performance...

Yohan Simard 4 years ago
parent
commit
01f8a7c558

+ 6
- 3
App.js View File

@@ -34,6 +34,9 @@ export default class App extends React.Component<Props, State> {
34 34
     constructor(props: Object) {
35 35
         super(props);
36 36
         LocaleManager.initTranslations();
37
+        this.onIntroDone = this.onIntroDone.bind(this);
38
+        this.loadAssetsAsync = this.loadAssetsAsync.bind(this);
39
+        this.onLoadFinished = this.onLoadFinished.bind(this);
37 40
     }
38 41
 
39 42
     /**
@@ -102,14 +105,14 @@ export default class App extends React.Component<Props, State> {
102 105
         if (this.state.isLoading) {
103 106
             return (
104 107
                 <AppLoading
105
-                    startAsync={() => this.loadAssetsAsync()}
106
-                    onFinish={() => this.onLoadFinished()}
108
+                    startAsync={this.loadAssetsAsync}
109
+                    onFinish={this.onLoadFinished}
107 110
                     onError={console.warn}
108 111
                 />
109 112
             );
110 113
         }
111 114
         if (this.state.showIntro || this.state.showUpdate) {
112
-            return <CustomIntroSlider onDone={() => this.onIntroDone()}
115
+            return <CustomIntroSlider onDone={this.onIntroDone}
113 116
                                       isUpdate={this.state.showUpdate && !this.state.showIntro}/>;
114 117
         } else {
115 118
             const AppNavigator = createAppContainerWithInitialRoute(AsyncStorageManager.getInstance().preferences.defaultStartScreen.current);

+ 10
- 8
components/BaseContainer.js View File

@@ -30,7 +30,6 @@ type State = {
30 30
 
31 31
 
32 32
 export default class BaseContainer extends React.Component<Props, State> {
33
-
34 33
     static defaultProps = {
35 34
         headerRightButton: <View/>,
36 35
         hasTabs: false,
@@ -46,9 +45,15 @@ export default class BaseContainer extends React.Component<Props, State> {
46 45
         isHeaderVisible: true,
47 46
     };
48 47
 
48
+    constructor() {
49
+        super();
50
+        this.toggle = this.toggle.bind(this);
51
+    }
52
+
49 53
     toggle() {
50 54
         this.props.navigation.toggleDrawer();
51 55
     }
56
+
52 57
     /**
53 58
      * Register for blur event to close side menu on screen change
54 59
      */
@@ -93,7 +98,9 @@ export default class BaseContainer extends React.Component<Props, State> {
93 98
             this.willFocusSubscription.remove();
94 99
     }
95 100
 
96
-    getMainContainer() {
101
+
102
+    render() {
103
+        // console.log("rendering BaseContainer");
97 104
         return (
98 105
             <Container>
99 106
                 {this.state.isHeaderVisible ?
@@ -104,7 +111,7 @@ export default class BaseContainer extends React.Component<Props, State> {
104 111
                         leftButton={
105 112
                             <Touchable
106 113
                                 style={{padding: 6}}
107
-                                onPress={() => this.toggle()}>
114
+                                onPress={this.toggle}>
108 115
                                 <CustomMaterialIcon
109 116
                                     color={Platform.OS === 'ios' ? ThemeManager.getCurrentThemeVariables().brandPrimary : "#fff"}
110 117
                                     icon="menu"/>
@@ -118,9 +125,4 @@ export default class BaseContainer extends React.Component<Props, State> {
118 125
             </Container>
119 126
         );
120 127
     }
121
-
122
-
123
-    render() {
124
-        return (this.getMainContainer());
125
-    }
126 128
 }

+ 25
- 7
components/CustomHeader.js View File

@@ -32,7 +32,6 @@ type Props = {
32 32
  * @prop navigation {Object} The navigation object from react navigation
33 33
  */
34 34
 export default class CustomHeader extends React.Component<Props> {
35
-
36 35
     static defaultProps = {
37 36
         hasBackButton: false,
38 37
         hasSearchField: false,
@@ -45,9 +44,25 @@ export default class CustomHeader extends React.Component<Props> {
45 44
         hasTabs: false,
46 45
     };
47 46
 
47
+    constructor() {
48
+        super();
49
+        this.onPressBack = this.onPressBack.bind(this);
50
+    }
51
+
52
+    shouldComponentUpdate(nextProps: Props): boolean {
53
+        return nextProps.title !== this.props.title ||
54
+            nextProps.subtitle !== this.props.subtitle ||
55
+            nextProps.hasBackButton !== this.props.hasBackButton ||
56
+            nextProps.hasSearchField !== this.props.hasSearchField ||
57
+            nextProps.shouldFocusSearchBar !== this.props.shouldFocusSearchBar ||
58
+            nextProps.hasTabs !== this.props.hasTabs ||
59
+            nextProps.rightButton !== this.props.rightButton ||
60
+            nextProps.leftButton !== this.props.leftButton;
61
+    }
62
+
48 63
     componentDidMount() {
49 64
         if (this.refs.searchInput !== undefined && this.refs.searchInput._root !== undefined && this.props.shouldFocusSearchBar) {
50
-            // does not work if called to early for some reason...
65
+            // does not work if called too early for some reason...
51 66
             setTimeout(() => this.refs.searchInput._root.focus(), 500);
52 67
         }
53 68
     }
@@ -67,7 +82,7 @@ export default class CustomHeader extends React.Component<Props> {
67 82
                         ref="searchInput"
68 83
                         placeholder={i18n.t('proximoScreen.search')}
69 84
                         placeholderTextColor={ThemeManager.getCurrentThemeVariables().toolbarPlaceholderColor}
70
-                        onChangeText={(text) => this.props.searchCallback(text)}/>
85
+                        onChangeText={this.props.searchCallback}/>
71 86
                 </Item>
72 87
             </Body>
73 88
         );
@@ -87,17 +102,20 @@ export default class CustomHeader extends React.Component<Props> {
87 102
     }
88 103
 
89 104
 
105
+    onPressBack() {
106
+        const backAction = NavigationActions.back();
107
+        this.props.navigation.dispatch(backAction);
108
+    }
109
+
90 110
     render() {
111
+        console.log("rendering CustomHeader");
91 112
         let button;
92 113
         // Does the app have a back button or a burger menu ?
93 114
         if (this.props.hasBackButton)
94 115
             button =
95 116
                 <Touchable
96 117
                     style={{padding: 6}}
97
-                    onPress={() => {
98
-                        const backAction = NavigationActions.back();
99
-                        this.props.navigation.dispatch(backAction);
100
-                    }}>
118
+                    onPress={this.onPressBack}>
101 119
                     <CustomMaterialIcon
102 120
                         color={Platform.OS === 'ios' ? ThemeManager.getCurrentThemeVariables().brandPrimary : "#fff"}
103 121
                         icon={Platform.OS === 'ios' ? 'chevron-left' : "arrow-left"}/>

+ 9
- 0
components/CustomMaterialIcon.js View File

@@ -30,7 +30,16 @@ export default class CustomMaterialIcon extends React.Component<Props> {
30 30
         width: 30,
31 31
     };
32 32
 
33
+    shouldComponentUpdate(nextProps: Props): boolean {
34
+        return nextProps.icon !== this.props.icon ||
35
+            nextProps.active !== this.props.active ||
36
+            nextProps.width !== this.props.width ||
37
+            nextProps.fontSize !== this.props.fontSize ||
38
+            nextProps.color !== this.props.color;
39
+    }
40
+
33 41
     render() {
42
+        // console.log("rendering icon " + this.props.icon);
34 43
         return (
35 44
             <Icon
36 45
                 active

+ 7
- 1
components/DashboardItem.js View File

@@ -25,13 +25,18 @@ type Props = {
25 25
 }
26 26
 
27 27
 export default class DashboardItem extends React.Component<Props> {
28
-
29 28
     static defaultProps = {
30 29
         isSquare: false,
31 30
         isSquareLeft: true,
32 31
         displayEvent: undefined,
33 32
     };
34 33
 
34
+    shouldComponentUpdate(nextProps: Props): boolean {
35
+        return nextProps.isAvailable !== this.props.isAvailable ||
36
+            nextProps.subtitle !== this.props.subtitle;
37
+    }
38
+
39
+
35 40
     /**
36 41
      * Convert the date string given by in the event list json to a date object
37 42
      * @param dateString
@@ -203,6 +208,7 @@ export default class DashboardItem extends React.Component<Props> {
203 208
 
204 209
 
205 210
     render() {
211
+        // console.log("rendering DashboardItem " + this.props.title);
206 212
         let marginRight = 10;
207 213
         if (this.props.isSquare) {
208 214
             if (this.props.isSquareLeft)

+ 44
- 31
components/FetchedDataSectionList.js View File

@@ -25,7 +25,6 @@ type State = {
25 25
  * Used by inheriting from it and redefining getters.
26 26
  */
27 27
 export default class FetchedDataSectionList extends React.Component<Props, State> {
28
-
29 28
     webDataManager: WebDataManager;
30 29
 
31 30
     willFocusSubscription: function;
@@ -46,8 +45,22 @@ export default class FetchedDataSectionList extends React.Component<Props, State
46 45
         super();
47 46
         this.webDataManager = new WebDataManager(fetchUrl);
48 47
         this.refreshTime = refreshTime;
48
+        // creating references to functions used in render()
49
+        this._onRefresh = this._onRefresh.bind(this);
50
+        this.renderSectionHeaderEmpty = this.renderSectionHeader.bind(this, true);
51
+        this.renderSectionHeaderNotEmpty = this.renderSectionHeader.bind(this, false);
52
+        this.renderItemEmpty = this.renderItem.bind(this, true);
53
+        this.renderItemNotEmpty = this.renderItem.bind(this, false);
54
+    }
55
+
56
+    shouldComponentUpdate(nextProps: Props, nextState: State): boolean {
57
+        return this.state.refreshing !== nextState.refreshing ||
58
+            nextState.firstLoading !== this.state.firstLoading ||
59
+            nextState.machinesWatched.length !== this.state.machinesWatched.length ||
60
+            nextState.fetchedData.len !== this.state.fetchedData.len;
49 61
     }
50 62
 
63
+
51 64
     /**
52 65
      * Get the translation for the header in the current language
53 66
      * @return {string}
@@ -74,17 +87,9 @@ export default class FetchedDataSectionList extends React.Component<Props, State
74 87
      */
75 88
     componentDidMount() {
76 89
         this.willFocusSubscription = this.props.navigation.addListener(
77
-            'willFocus',
78
-            () => {
79
-                this.onScreenFocus();
80
-            }
81
-        );
90
+            'willFocus', this.onScreenFocus.bind(this));
82 91
         this.willBlurSubscription = this.props.navigation.addListener(
83
-            'willBlur',
84
-            () => {
85
-                this.onScreenBlur();
86
-            }
87
-        );
92
+            'willBlur', this.onScreenBlur.bind(this));
88 93
     }
89 94
 
90 95
     /**
@@ -93,7 +98,7 @@ export default class FetchedDataSectionList extends React.Component<Props, State
93 98
     onScreenFocus() {
94 99
         this._onRefresh();
95 100
         if (this.refreshTime > 0)
96
-            this.refreshInterval = setInterval(() => this._onRefresh(), this.refreshTime)
101
+            this.refreshInterval = setInterval(this._onRefresh.bind(this), this.refreshTime)
97 102
     }
98 103
 
99 104
     /**
@@ -117,7 +122,7 @@ export default class FetchedDataSectionList extends React.Component<Props, State
117 122
      * Refresh data and show a toast if any error occurred
118 123
      * @private
119 124
      */
120
-    _onRefresh = () => {
125
+    _onRefresh() {
121 126
         let canRefresh;
122 127
         if (this.lastRefresh !== undefined)
123 128
             canRefresh = (new Date().getTime() - this.lastRefresh.getTime()) / 1000 > this.minTimeBetweenRefresh;
@@ -144,8 +149,7 @@ export default class FetchedDataSectionList extends React.Component<Props, State
144 149
                     this.webDataManager.showUpdateToast(this.getUpdateToastTranslations()[0], this.getUpdateToastTranslations()[1]);
145 150
                 });
146 151
         }
147
-
148
-    };
152
+    }
149 153
 
150 154
     /**
151 155
      * Get the render item to be used for display in the list.
@@ -153,10 +157,9 @@ export default class FetchedDataSectionList extends React.Component<Props, State
153 157
      *
154 158
      * @param item
155 159
      * @param section
156
-     * @param data
157 160
      * @return {*}
158 161
      */
159
-    getRenderItem(item: Object, section: Object, data: Object) {
162
+    getRenderItem(item: Object, section: Object) {
160 163
         return <View/>;
161 164
     }
162 165
 
@@ -222,6 +225,11 @@ export default class FetchedDataSectionList extends React.Component<Props, State
222 225
         return [];
223 226
     }
224 227
 
228
+
229
+    datasetKeyExtractor(item: Object) {
230
+        return item.text
231
+    }
232
+
225 233
     /**
226 234
      * Create the dataset when no fetched data is available.
227 235
      * No need to be overridden, has good defaults.
@@ -243,7 +251,7 @@ export default class FetchedDataSectionList extends React.Component<Props, State
243 251
                             'access-point-network-off'
244 252
                     }
245 253
                 ],
246
-                keyExtractor: (item: Object) => item.text,
254
+                keyExtractor: this.datasetKeyExtractor,
247 255
             }
248 256
         ];
249 257
     }
@@ -275,6 +283,19 @@ export default class FetchedDataSectionList extends React.Component<Props, State
275 283
         return true;
276 284
     }
277 285
 
286
+
287
+    renderSectionHeader(isEmpty, {section: {title}}) {
288
+        return isEmpty ?
289
+            <View/> :
290
+            this.getRenderSectionHeader(title)
291
+    }
292
+
293
+    renderItem(isEmpty, {item, section}) {
294
+        return isEmpty ?
295
+            this.getEmptyRenderItem(item.text, item.isSpinner, item.icon) :
296
+            this.getRenderItem(item, section)
297
+    }
298
+
278 299
     /**
279 300
      * Get the section list render using the generated dataset
280 301
      *
@@ -295,16 +316,8 @@ export default class FetchedDataSectionList extends React.Component<Props, State
295 316
                         onRefresh={this._onRefresh}
296 317
                     />
297 318
                 }
298
-                renderSectionHeader={({section: {title}}) =>
299
-                    isEmpty ?
300
-                        <View/> :
301
-                        this.getRenderSectionHeader(title)
302
-                }
303
-                renderItem={({item, section}) =>
304
-                    isEmpty ?
305
-                        this.getEmptyRenderItem(item.text, item.isSpinner, item.icon) :
306
-                        this.getRenderItem(item, section, dataset)
307
-                }
319
+                renderSectionHeader={isEmpty ? this.renderSectionHeaderEmpty : this.renderSectionHeaderNotEmpty}
320
+                renderItem={isEmpty ? this.renderItemEmpty : this.renderItemNotEmpty}
308 321
                 style={{minHeight: 300, width: '100%'}}
309 322
                 contentContainerStyle={
310 323
                     isEmpty ?
@@ -351,11 +364,12 @@ export default class FetchedDataSectionList extends React.Component<Props, State
351 364
     }
352 365
 
353 366
     render() {
354
-        const nav = this.props.navigation;
367
+        // console.log("rendering FetchedDataSectionList");
355 368
         const dataset = this.createDataset(this.state.fetchedData);
356 369
         return (
357 370
             <BaseContainer
358
-                navigation={nav} headerTitle={this.getHeaderTranslation()}
371
+                navigation={this.props.navigation}
372
+                headerTitle={this.getHeaderTranslation()}
359 373
                 headerRightButton={this.getRightButton()}
360 374
                 hasTabs={this.hasTabs()}
361 375
                 hasBackButton={this.hasBackButton()}
@@ -375,5 +389,4 @@ export default class FetchedDataSectionList extends React.Component<Props, State
375 389
             </BaseContainer>
376 390
         );
377 391
     }
378
-
379 392
 }

+ 24
- 9
components/Sidebar.js View File

@@ -103,21 +103,35 @@ export default class SideBar extends React.Component<Props, State> {
103 103
                 icon: "information",
104 104
             },
105 105
         ];
106
+        this.getRenderItem = this.getRenderItem.bind(this);
106 107
     }
107 108
 
108
-    getRenderItem(item: Object) {
109
+    shouldComponentUpdate(nextProps: Props, nextState: State): boolean {
110
+        return nextState.active !== this.state.active;
111
+    }
112
+
113
+
114
+    onListItemPress(item) {
115
+        if (item.link !== undefined)
116
+            Linking.openURL(item.link).catch((err) => console.error('Error opening link', err));
117
+        else
118
+            this.navigateToScreen(item.route);
119
+    }
120
+
121
+
122
+    listKeyExtractor(item) {
123
+        return item.route;
124
+    }
125
+
126
+
127
+    getRenderItem({item}: Object) {
109 128
         if (item.icon !== undefined) {
110 129
             return (
111 130
                 <ListItem
112 131
                     button
113 132
                     noBorder
114 133
                     selected={this.state.active === item.route}
115
-                    onPress={() => {
116
-                        if (item.link !== undefined)
117
-                            Linking.openURL(item.link).catch((err) => console.error('Error opening link', err));
118
-                        else
119
-                            this.navigateToScreen(item.route);
120
-                    }}
134
+                    onPress={this.onListItemPress.bind(this, item)}
121 135
                 >
122 136
                     <Left>
123 137
                         <CustomMaterialIcon
@@ -164,6 +178,7 @@ export default class SideBar extends React.Component<Props, State> {
164 178
     };
165 179
 
166 180
     render() {
181
+        // console.log("rendering SideBar");
167 182
         return (
168 183
             <Container style={{
169 184
                 backgroundColor: ThemeManager.getCurrentThemeVariables().sideMenuBgColor,
@@ -172,8 +187,8 @@ export default class SideBar extends React.Component<Props, State> {
172 187
                 <FlatList
173 188
                     data={this.dataSet}
174 189
                     extraData={this.state}
175
-                    keyExtractor={(item) => item.route}
176
-                    renderItem={({item}) => this.getRenderItem(item)}
190
+                    keyExtractor={this.listKeyExtractor}
191
+                    renderItem={this.getRenderItem}
177 192
                 />
178 193
             </Container>
179 194
         );

+ 1
- 0
components/WebViewScreen.js View File

@@ -133,6 +133,7 @@ export default class WebViewScreen extends React.Component<Props> {
133 133
     }
134 134
 
135 135
     render() {
136
+        // console.log("rendering WebViewScreen");
136 137
         const nav = this.props.navigation;
137 138
         this.webviewArray = [];
138 139
         return (

+ 37
- 18
screens/HomeScreen.js View File

@@ -40,6 +40,10 @@ export default class HomeScreen extends FetchedDataSectionList {
40 40
 
41 41
     constructor() {
42 42
         super(DATA_URL, REFRESH_TIME);
43
+        this.proxiwashClickAction = this.proxiwashClickAction.bind(this);
44
+        this.tutorinsaClickAction = this.tutorinsaClickAction.bind(this);
45
+        this.menuClickAction = this.menuClickAction.bind(this);
46
+        this.proximoClickAction = this.proximoClickAction.bind(this);
43 47
     }
44 48
 
45 49
     /**
@@ -289,6 +293,14 @@ export default class HomeScreen extends FetchedDataSectionList {
289 293
     }
290 294
 
291 295
 
296
+    clickAction(isAvailable, displayEvent) {
297
+        if (isAvailable)
298
+            this.props.navigation.navigate('PlanningDisplayScreen', {data: displayEvent});
299
+        else
300
+            this.props.navigation.navigate('PlanningScreen');
301
+    };
302
+
303
+
292 304
     getDashboardEventItem(content: Array<Object>) {
293 305
         let icon = 'calendar-range';
294 306
         let color = ThemeManager.getCurrentThemeVariables().planningColor;
@@ -310,12 +322,6 @@ export default class HomeScreen extends FetchedDataSectionList {
310 322
                 </Text>;
311 323
         } else
312 324
             subtitle = i18n.t('homeScreen.dashboard.todayEventsSubtitleNA');
313
-        let clickAction = () => {
314
-            if (isAvailable)
315
-                this.props.navigation.navigate('PlanningDisplayScreen', {data: displayEvent});
316
-            else
317
-                this.props.navigation.navigate('PlanningScreen');
318
-        };
319 325
 
320 326
         let displayEvent = this.getDisplayEvent(futureEvents);
321 327
 
@@ -324,7 +330,7 @@ export default class HomeScreen extends FetchedDataSectionList {
324 330
                 subtitle={subtitle}
325 331
                 color={color}
326 332
                 icon={icon}
327
-                clickAction={() => clickAction()}
333
+                clickAction={this.clickAction.bind(this, isAvailable, displayEvent)}
328 334
                 title={title}
329 335
                 isAvailable={isAvailable}
330 336
                 displayEvent={displayEvent}
@@ -332,6 +338,14 @@ export default class HomeScreen extends FetchedDataSectionList {
332 338
         );
333 339
     }
334 340
 
341
+    proximoClickAction() {
342
+        this.props.navigation.navigate('Proximo');
343
+    }
344
+
345
+    menuClickAction() {
346
+        this.props.navigation.navigate('SelfMenuScreen');
347
+    }
348
+
335 349
 
336 350
     getDashboardBottomItem(content: Array<Object>) {
337 351
         let proximoData = content[0]['data'];
@@ -355,7 +369,6 @@ export default class HomeScreen extends FetchedDataSectionList {
355 369
                 </Text>;
356 370
         } else
357 371
             proximoSubtitle = i18n.t('homeScreen.dashboard.proximoSubtitleNA');
358
-        let proximoClickAction = () => this.props.navigation.navigate('Proximo');
359 372
 
360 373
 
361 374
         let menuIcon = 'silverware-fork-knife';
@@ -367,7 +380,6 @@ export default class HomeScreen extends FetchedDataSectionList {
367 380
             menuSubtitle = i18n.t('homeScreen.dashboard.menuSubtitle');
368 381
         } else
369 382
             menuSubtitle = i18n.t('homeScreen.dashboard.menuSubtitleNA');
370
-        let menuClickAction = () => this.props.navigation.navigate('SelfMenuScreen');
371 383
         return (
372 384
             <View style={{
373 385
                 flexDirection: 'row',
@@ -379,7 +391,7 @@ export default class HomeScreen extends FetchedDataSectionList {
379 391
                     subtitle={menuSubtitle}
380 392
                     color={menuColor}
381 393
                     icon={menuIcon}
382
-                    clickAction={() => menuClickAction()}
394
+                    clickAction={this.menuClickAction}
383 395
                     title={menuTitle}
384 396
                     isAvailable={isMenuAvailable}
385 397
                     isSquareLeft={true}/>
@@ -388,13 +400,22 @@ export default class HomeScreen extends FetchedDataSectionList {
388 400
                     subtitle={proximoSubtitle}
389 401
                     color={proximoColor}
390 402
                     icon={proximoIcon}
391
-                    clickAction={() => proximoClickAction()}
403
+                    clickAction={this.proximoClickAction}
392 404
                     title={proximoTitle}
393 405
                     isAvailable={isProximoAvailable}/>
394 406
             </View>
395 407
         );
396 408
     }
397 409
 
410
+    proxiwashClickAction() {
411
+        this.props.navigation.navigate('Proxiwash');
412
+    }
413
+
414
+    tutorinsaClickAction() {
415
+        this.props.navigation.navigate('TutorInsaScreen');
416
+    }
417
+
418
+
398 419
     getDashboardMiddleItem(content: Array<Object>) {
399 420
         let proxiwashData = content[0]['data'];
400 421
         let tutorinsaData = content[1]['data'];
@@ -449,7 +470,6 @@ export default class HomeScreen extends FetchedDataSectionList {
449 470
                 </Text>;
450 471
         } else
451 472
             proxiwashSubtitle = i18n.t('homeScreen.dashboard.proxiwashSubtitleNA');
452
-        let proxiwashClickAction = () => this.props.navigation.navigate('Proxiwash');
453 473
 
454 474
         let tutorinsaIcon = 'school';
455 475
         let tutorinsaColor = ThemeManager.getCurrentThemeVariables().tutorinsaColor;
@@ -470,7 +490,6 @@ export default class HomeScreen extends FetchedDataSectionList {
470 490
                 </Text>;
471 491
         } else
472 492
             tutorinsaSubtitle = i18n.t('homeScreen.dashboard.tutorinsaSubtitleNA');
473
-        let tutorinsaClickAction = () => this.props.navigation.navigate('TutorInsaScreen');
474 493
 
475 494
         return (
476 495
             <View style={{
@@ -483,7 +502,7 @@ export default class HomeScreen extends FetchedDataSectionList {
483 502
                     subtitle={proxiwashSubtitle}
484 503
                     color={proxiwashColor}
485 504
                     icon={proxiwashIcon}
486
-                    clickAction={() => proxiwashClickAction()}
505
+                    clickAction={this.proxiwashClickAction}
487 506
                     title={proxiwashTitle}
488 507
                     isAvailable={proxiwashIsAvailable}
489 508
                     isSquareLeft={true}/>
@@ -492,7 +511,7 @@ export default class HomeScreen extends FetchedDataSectionList {
492 511
                     subtitle={tutorinsaSubtitle}
493 512
                     color={tutorinsaColor}
494 513
                     icon={tutorinsaIcon}
495
-                    clickAction={() => tutorinsaClickAction()}
514
+                    clickAction={this.tutorinsaClickAction}
496 515
                     title={tutorinsaTitle}
497 516
                     isAvailable={tutorinsaIsAvailable}/>
498 517
             </View>
@@ -500,7 +519,7 @@ export default class HomeScreen extends FetchedDataSectionList {
500 519
     }
501 520
 
502 521
 
503
-    getRenderItem(item: Object, section: Object, data: Object) {
522
+    getRenderItem(item: Object, section: Object) {
504 523
         return (
505 524
             section['id'] === SECTIONS_ID[0] ? this.getDashboardItem(item) :
506 525
                 <Card style={{
@@ -525,7 +544,7 @@ export default class HomeScreen extends FetchedDataSectionList {
525 544
                     }}>
526 545
                         <Body>
527 546
                             {item.full_picture !== '' && item.full_picture !== undefined ?
528
-                                <TouchableOpacity onPress={() => openWebLink(item.full_picture)}
547
+                                <TouchableOpacity onPress={openWebLink.bind(null, item.full_picture)}
529 548
                                                   style={{width: '100%', height: 250, marginBottom: 5}}>
530 549
                                     <Image source={{uri: item.full_picture}}
531 550
                                            style={{flex: 1, resizeMode: "contain"}}
@@ -547,7 +566,7 @@ export default class HomeScreen extends FetchedDataSectionList {
547 566
                     }}>
548 567
                         <Left>
549 568
                             <Button transparent
550
-                                    onPress={() => openWebLink(item.permalink_url)}>
569
+                                    onPress={openWebLink.bind(null, item.permalink_url)}>
551 570
                                 <CustomMaterialIcon
552 571
                                     icon="facebook"
553 572
                                     color="#57aeff"

+ 3
- 3
screens/PlanningDisplayScreen.js View File

@@ -14,7 +14,7 @@ type Props = {
14 14
     navigation: Object,
15 15
 };
16 16
 
17
-function openWebLink(link) {
17
+function openWebLink(event, link) {
18 18
     Linking.openURL(link).catch((err) => console.error('Error opening link', err));
19 19
 }
20 20
 
@@ -22,8 +22,8 @@ function openWebLink(link) {
22 22
  * Class defining an about screen. This screen shows the user information about the app and it's author.
23 23
  */
24 24
 export default class PlanningDisplayScreen extends React.Component<Props> {
25
-
26 25
     render() {
26
+        // console.log("rendering planningDisplayScreen");
27 27
         const nav = this.props.navigation;
28 28
         const displayData = nav.getParam('data', []);
29 29
         return (
@@ -60,7 +60,7 @@ export default class PlanningDisplayScreen extends React.Component<Props> {
60 60
                                   },
61 61
                                   div: {color: ThemeManager.getCurrentThemeVariables().textColor}
62 62
                               }}
63
-                              onLinkPress={(event, link) => openWebLink(link)}/>
63
+                              onLinkPress={openWebLink}/>
64 64
                         : <View/>}
65 65
                 </Content>
66 66
             </Container>

+ 39
- 18
screens/PlanningScreen.js View File

@@ -56,6 +56,7 @@ export default class PlanningScreen extends React.Component<Props, State> {
56 56
 
57 57
     didFocusSubscription: Function;
58 58
     willBlurSubscription: Function;
59
+
59 60
     state = {
60 61
         refreshing: false,
61 62
         agendaItems: {},
@@ -76,6 +77,22 @@ export default class PlanningScreen extends React.Component<Props, State> {
76 77
         if (i18n.currentLocale().startsWith("fr")) {
77 78
             LocaleConfig.defaultLocale = 'fr';
78 79
         }
80
+
81
+        // Create references for functions required in the render function
82
+        this._onRefresh = this._onRefresh.bind(this);
83
+        this.onCalendarToggled = this.onCalendarToggled.bind(this);
84
+        this.getRenderItem = this.getRenderItem.bind(this);
85
+        this.getRenderEmptyDate = this.getRenderEmptyDate.bind(this);
86
+        this.setAgendaRef = this.setAgendaRef.bind(this);
87
+        this.onCalendarToggled = this.onCalendarToggled.bind(this);
88
+        this.onCalendarToggled = this.onCalendarToggled.bind(this);
89
+        this.onBackButtonPressAndroid = this.onBackButtonPressAndroid.bind(this);
90
+    }
91
+
92
+    shouldComponentUpdate(nextProps: Props, nextState: State): boolean {
93
+        return nextState.refreshing === false && this.state.refreshing === true ||
94
+            nextState.agendaItems !== this.state.agendaItems ||
95
+            nextState.calendarShowing !== this.state.calendarShowing;
79 96
     }
80 97
 
81 98
     componentDidMount() {
@@ -90,7 +107,7 @@ export default class PlanningScreen extends React.Component<Props, State> {
90 107
         );
91 108
     }
92 109
 
93
-    onBackButtonPressAndroid = () => {
110
+    onBackButtonPressAndroid() {
94 111
         if (this.state.calendarShowing) {
95 112
             this.agendaRef.chooseDay(this.agendaRef.state.selectedDay);
96 113
             return true;
@@ -126,10 +143,6 @@ export default class PlanningScreen extends React.Component<Props, State> {
126 143
     }
127 144
 
128 145
     getRenderItem(item: Object) {
129
-        let navData = {
130
-            data: item
131
-        };
132
-        const nav = this.props.navigation;
133 146
         return (
134 147
             <Touchable
135 148
                 style={{
@@ -138,7 +151,7 @@ export default class PlanningScreen extends React.Component<Props, State> {
138 151
                     marginRight: 10,
139 152
                     marginTop: 17,
140 153
                 }}
141
-                onPress={() => nav.navigate('PlanningDisplayScreen', navData)}>
154
+                onPress={() => this.props.navigation.navigate('PlanningDisplayScreen', {data: item})}>
142 155
                 <View style={{
143 156
                     padding: 10,
144 157
                     flex: 1,
@@ -252,38 +265,46 @@ export default class PlanningScreen extends React.Component<Props, State> {
252 265
         }
253 266
     }
254 267
 
268
+    setAgendaRef(ref) {
269
+        this.agendaRef = ref;
270
+    }
271
+
272
+    onCalendarToggled(calendarOpened) {
273
+        this.setState({calendarShowing: calendarOpened});
274
+    }
275
+
276
+    currentDate = this.getCurrentDate();
277
+
255 278
     render() {
256
-        const nav = this.props.navigation;
279
+        // console.log("rendering PlanningScreen");
257 280
         return (
258
-            <BaseContainer navigation={nav} headerTitle={i18n.t('screens.planning')}>
281
+            <BaseContainer navigation={this.props.navigation} headerTitle={i18n.t('screens.planning')}>
259 282
                 <Agenda
260 283
                     // the list of items that have to be displayed in agenda. If you want to render item as empty date
261 284
                     // the value of date key kas to be an empty array []. If there exists no value for date key it is
262 285
                     // considered that the date in question is not yet loaded
263 286
                     items={this.state.agendaItems}
264 287
                     // initially selected day
265
-                    selected={this.getCurrentDate()}
288
+                    selected={this.currentDate}
266 289
                     // Minimum date that can be selected, dates before minDate will be grayed out. Default = undefined
267
-                    minDate={this.getCurrentDate()}
290
+                    minDate={this.currentDate}
268 291
                     // Max amount of months allowed to scroll to the past. Default = 50
269 292
                     pastScrollRange={1}
270 293
                     // Max amount of months allowed to scroll to the future. Default = 50
271 294
                     futureScrollRange={AGENDA_MONTH_SPAN}
272 295
                     // If provided, a standard RefreshControl will be added for "Pull to Refresh" functionality. Make sure to also set the refreshing prop correctly.
273
-                    onRefresh={() => this._onRefresh()}
296
+                    onRefresh={this._onRefresh}
274 297
                     // callback that fires when the calendar is opened or closed
275
-                    onCalendarToggled={(calendarOpened) => {
276
-                        this.setState({calendarShowing: calendarOpened})
277
-                    }}
298
+                    onCalendarToggled={this.onCalendarToggled}
278 299
                     // Set this true while waiting for new data from a refresh
279 300
                     refreshing={this.state.refreshing}
280
-                    renderItem={(item) => this.getRenderItem(item)}
281
-                    renderEmptyDate={() => this.getRenderEmptyDate()}
282
-                    rowHasChanged={() => this.rowHasChanged()}
301
+                    renderItem={this.getRenderItem}
302
+                    renderEmptyDate={this.getRenderEmptyDate}
303
+                    rowHasChanged={this.rowHasChanged}
283 304
                     // If firstDay=1 week starts from Monday. Note that dayNames and dayNamesShort should still start from Sunday.
284 305
                     firstDay={1}
285 306
                     // ref to this agenda in order to handle back button event
286
-                    ref={(ref) => this.agendaRef = ref}
307
+                    ref={this.setAgendaRef}
287 308
                     // agenda theme
288 309
                     theme={{
289 310
                         backgroundColor: ThemeManager.getCurrentThemeVariables().agendaBackgroundColor,

+ 58
- 34
screens/Proximo/ProximoListScreen.js View File

@@ -76,6 +76,11 @@ export default class ProximoListScreen extends React.Component<Props, State> {
76 76
         super(props);
77 77
         this.modalRef = React.createRef();
78 78
         this.originalData = this.navData['data'];
79
+        this.search = this.search.bind(this);
80
+        this.selectSortModeName = this.selectSortModeName.bind(this);
81
+        this.selectSortModePrice = this.selectSortModePrice.bind(this);
82
+        this.showMenu = this.showMenu.bind(this);
83
+        this.renderItem = this.renderItem.bind(this);
79 84
     }
80 85
 
81 86
     /**
@@ -260,6 +265,19 @@ export default class ProximoListScreen extends React.Component<Props, State> {
260 265
         }
261 266
     }
262 267
 
268
+    selectSortModeName() {
269
+        this.sortModeSelected(sortMode.name);
270
+    }
271
+
272
+    selectSortModePrice() {
273
+        this.sortModeSelected(sortMode.price);
274
+    }
275
+
276
+    showMenu() {
277
+        this._menu.show();
278
+    }
279
+
280
+
263 281
     getSortMenu() {
264 282
         return (
265 283
             <Menu
@@ -267,9 +285,7 @@ export default class ProximoListScreen extends React.Component<Props, State> {
267 285
                 button={
268 286
                     <Touchable
269 287
                         style={{padding: 6}}
270
-                        onPress={() =>
271
-                            this._menu.show()
272
-                        }>
288
+                        onPress={this.showMenu}>
273 289
                         <CustomMaterialIcon
274 290
                             color={Platform.OS === 'ios' ? ThemeManager.getCurrentThemeVariables().brandPrimary : "#fff"}
275 291
                             icon={'sort'}/>
@@ -277,12 +293,12 @@ export default class ProximoListScreen extends React.Component<Props, State> {
277 293
                 }
278 294
             >
279 295
                 <MenuItem
280
-                    onPress={() => this.sortModeSelected(sortMode.name)}>
296
+                    onPress={this.selectSortModeName}>
281 297
                     {this.state.sortNameIcon}
282 298
                     {i18n.t('proximoScreen.sortName')}
283 299
                 </MenuItem>
284 300
                 <MenuItem
285
-                    onPress={() => this.sortModeSelected(sortMode.price)}>
301
+                    onPress={this.selectSortModePrice}>
286 302
                     {this.state.sortPriceIcon}
287 303
                     {i18n.t('proximoScreen.sortPrice')}
288 304
                 </MenuItem>
@@ -290,7 +306,41 @@ export default class ProximoListScreen extends React.Component<Props, State> {
290 306
         );
291 307
     }
292 308
 
309
+    renderItem({item}) {
310
+        return (<ListItem
311
+            thumbnail
312
+            onPress={() => {
313
+                this.showItemDetails(item);
314
+            }}
315
+        >
316
+            <Left>
317
+                <Thumbnail square source={{uri: item.image}}/>
318
+            </Left>
319
+            <Body>
320
+                <Text style={{marginLeft: 20}}>
321
+                    {item.name}
322
+                </Text>
323
+                <Text note style={{
324
+                    marginLeft: 20,
325
+                    color: this.getStockColor(parseInt(item.quantity))
326
+                }}>
327
+                    {item.quantity + ' ' + i18n.t('proximoScreen.inStock')}
328
+                </Text>
329
+            </Body>
330
+            <Right>
331
+                <Text style={{fontWeight: "bold"}}>
332
+                    {item.price}€
333
+                </Text>
334
+            </Right>
335
+        </ListItem>);
336
+    }
337
+
338
+    keyExtractor(item) {
339
+        return item.name + item.code;
340
+    }
341
+
293 342
     render() {
343
+        // console.log("rendering ProximoListScreen");
294 344
         const nav = this.props.navigation;
295 345
         return (
296 346
             <Container>
@@ -303,7 +353,7 @@ export default class ProximoListScreen extends React.Component<Props, State> {
303 353
                     hasBackButton={true}
304 354
                     navigation={nav}
305 355
                     hasSearchField={true}
306
-                    searchCallback={(text) => this.search(text)}
356
+                    searchCallback={this.search}
307 357
                     shouldFocusSearchBar={this.shouldFocusSearchBar}
308 358
                     rightButton={this.getSortMenu()}
309 359
                 />
@@ -311,35 +361,9 @@ export default class ProximoListScreen extends React.Component<Props, State> {
311 361
                 <FlatList
312 362
                     data={this.state.currentlyDisplayedData}
313 363
                     extraData={this.state.currentlyDisplayedData}
314
-                    keyExtractor={(item) => item.name + item.code}
364
+                    keyExtractor={this.keyExtractor}
315 365
                     style={{minHeight: 300, width: '100%'}}
316
-                    renderItem={({item}) =>
317
-                        <ListItem
318
-                            thumbnail
319
-                            onPress={() => {
320
-                                this.showItemDetails(item);
321
-                            }}
322
-                        >
323
-                            <Left>
324
-                                <Thumbnail square source={{uri: item.image}}/>
325
-                            </Left>
326
-                            <Body>
327
-                                <Text style={{marginLeft: 20}}>
328
-                                    {item.name}
329
-                                </Text>
330
-                                <Text note style={{
331
-                                    marginLeft: 20,
332
-                                    color: this.getStockColor(parseInt(item.quantity))
333
-                                }}>
334
-                                    {item.quantity + ' ' + i18n.t('proximoScreen.inStock')}
335
-                                </Text>
336
-                            </Body>
337
-                            <Right>
338
-                                <Text style={{fontWeight: "bold"}}>
339
-                                    {item.price}€
340
-                                </Text>
341
-                            </Right>
342
-                        </ListItem>}
366
+                    renderItem={this.renderItem}
343 367
                 />
344 368
             </Container>
345 369
         );

+ 12
- 4
screens/Proximo/ProximoMainScreen.js View File

@@ -20,6 +20,8 @@ export default class ProximoMainScreen extends FetchedDataSectionList {
20 20
 
21 21
     constructor() {
22 22
         super(DATA_URL, 0);
23
+        this.onPressSearchBtn = this.onPressSearchBtn.bind(this);
24
+        this.onPressAboutBtn = this.onPressAboutBtn.bind(this);
23 25
     }
24 26
 
25 27
     static sortFinalData(a: Object, b: Object) {
@@ -100,7 +102,7 @@ export default class ProximoMainScreen extends FetchedDataSectionList {
100 102
         return availableArticles;
101 103
     }
102 104
 
103
-    getRightButton() {
105
+    onPressSearchBtn() {
104 106
         let searchScreenData = {
105 107
             shouldFocusSearchBar: true,
106 108
             data: {
@@ -113,8 +115,14 @@ export default class ProximoMainScreen extends FetchedDataSectionList {
113 115
                     this.getAvailableArticles(this.state.fetchedData.articles, undefined) : []
114 116
             },
115 117
         };
118
+        this.props.navigation.navigate('ProximoListScreen', searchScreenData);
119
+    }
116 120
 
121
+    onPressAboutBtn() {
122
+        this.props.navigation.navigate('ProximoAboutScreen');
123
+    }
117 124
 
125
+    getRightButton() {
118 126
         return (
119 127
             <View
120 128
                 style={{
@@ -122,14 +130,14 @@ export default class ProximoMainScreen extends FetchedDataSectionList {
122 130
                 }}>
123 131
                 <Touchable
124 132
                     style={{padding: 6}}
125
-                    onPress={() => this.props.navigation.navigate('ProximoListScreen', searchScreenData)}>
133
+                    onPress={this.onPressSearchBtn}>
126 134
                     <CustomMaterialIcon
127 135
                         color={Platform.OS === 'ios' ? ThemeManager.getCurrentThemeVariables().brandPrimary : "#fff"}
128 136
                         icon="magnify"/>
129 137
                 </Touchable>
130 138
                 <Touchable
131 139
                     style={{padding: 6}}
132
-                    onPress={() => this.props.navigation.navigate('ProximoAboutScreen')}>
140
+                    onPress={this.onPressAboutBtn}>
133 141
                     <CustomMaterialIcon
134 142
                         color={Platform.OS === 'ios' ? ThemeManager.getCurrentThemeVariables().brandPrimary : "#fff"}
135 143
                         icon="information"/>
@@ -138,7 +146,7 @@ export default class ProximoMainScreen extends FetchedDataSectionList {
138 146
         );
139 147
     }
140 148
 
141
-    getRenderItem(item: Object, section: Object, data: Object) {
149
+    getRenderItem(item: Object, section: Object) {
142 150
         let dataToSend = {
143 151
             shouldFocusSearchBar: false,
144 152
             data: item,

+ 8
- 3
screens/Proxiwash/ProxiwashScreen.js View File

@@ -75,6 +75,8 @@ export default class ProxiwashScreen extends FetchedDataSectionList {
75 75
             machinesWatched: [],
76 76
         };
77 77
         this.setMinTimeRefresh(30);
78
+
79
+        this.navigateToAboutScreen = this.navigateToAboutScreen.bind(this);
78 80
     }
79 81
 
80 82
     /**
@@ -272,11 +274,15 @@ export default class ProxiwashScreen extends FetchedDataSectionList {
272 274
         );
273 275
     }
274 276
 
277
+    navigateToAboutScreen() {
278
+        this.props.navigation.navigate('ProxiwashAboutScreen');
279
+    }
280
+
275 281
     getRightButton(): * {
276 282
         return (
277 283
             <Touchable
278 284
                 style={{padding: 6}}
279
-                onPress={() => this.props.navigation.navigate('ProxiwashAboutScreen')}>
285
+                onPress={this.navigateToAboutScreen}>
280 286
                 <CustomMaterialIcon
281 287
                     color={Platform.OS === 'ios' ? ThemeManager.getCurrentThemeVariables().brandPrimary : "#fff"}
282 288
                     icon="information"/>
@@ -289,10 +295,9 @@ export default class ProxiwashScreen extends FetchedDataSectionList {
289 295
      *
290 296
      * @param item The object containing the item's FetchedData
291 297
      * @param section The object describing the current SectionList section
292
-     * @param data The full FetchedData used by the SectionList
293 298
      * @returns {React.Node}
294 299
      */
295
-    getRenderItem(item: Object, section: Object, data: Object) {
300
+    getRenderItem(item: Object, section: Object) {
296 301
         let isMachineRunning = MACHINE_STATES[item.state] === MACHINE_STATES["EN COURS"];
297 302
         let machineName = (section.title === i18n.t('proxiwashScreen.dryers') ? i18n.t('proxiwashScreen.dryer') : i18n.t('proxiwashScreen.washer')) + ' n°' + item.number;
298 303
         let isDryer = section.title === i18n.t('proxiwashScreen.dryers');

+ 1
- 1
screens/SelfMenuScreen.js View File

@@ -119,7 +119,7 @@ export default class SelfMenuScreen extends FetchedDataSectionList {
119 119
         );
120 120
     }
121 121
 
122
-    getRenderItem(item: Object, section: Object, data: Object) {
122
+    getRenderItem(item: Object, section: Object) {
123 123
         return (
124 124
             <Card style={{
125 125
                 flex: 0,

Loading…
Cancel
Save