Browse Source

Improved screen changing performances and removed tab screen animations

Arnaud Vergnet 1 year ago
parent
commit
01e3195be7

+ 9
- 6
App.js View File

@@ -9,7 +9,6 @@ import {AppLoading} from 'expo';
9 9
 import type {CustomTheme} from "./src/managers/ThemeManager";
10 10
 import ThemeManager from './src/managers/ThemeManager';
11 11
 import {NavigationContainer} from '@react-navigation/native';
12
-import {createStackNavigator} from '@react-navigation/stack';
13 12
 import DrawerNavigator from './src/navigation/DrawerNavigator';
14 13
 import {initExpoToken} from "./src/utils/Notifications";
15 14
 import {Provider as PaperProvider} from 'react-native-paper';
@@ -18,6 +17,11 @@ import Update from "./src/constants/Update";
18 17
 import ConnectionManager from "./src/managers/ConnectionManager";
19 18
 import URLHandler from "./src/utils/URLHandler";
20 19
 import {setSafeBounceHeight} from "react-navigation-collapsible";
20
+import {enableScreens} from 'react-native-screens';
21
+
22
+// Native optimizations https://reactnavigation.org/docs/react-native-screens
23
+enableScreens();
24
+
21 25
 
22 26
 YellowBox.ignoreWarnings([ // collapsible headers cause this warning, just ignore as it is not an issue
23 27
     'Non-serializable values were found in the navigation state',
@@ -33,8 +37,6 @@ type State = {
33 37
     currentTheme: CustomTheme | null,
34 38
 };
35 39
 
36
-const Stack = createStackNavigator();
37
-
38 40
 export default class App extends React.Component<Props, State> {
39 41
 
40 42
     state = {
@@ -190,9 +192,10 @@ export default class App extends React.Component<Props, State> {
190 192
             return (
191 193
                 <PaperProvider theme={this.state.currentTheme}>
192 194
                     <NavigationContainer theme={this.state.currentTheme} ref={this.navigatorRef}>
193
-                        <Stack.Navigator headerMode="none">
194
-                            <Stack.Screen name="Root" component={this.createDrawerNavigator}/>
195
-                        </Stack.Navigator>
195
+                        <DrawerNavigator
196
+                            defaultHomeRoute={this.defaultHomeRoute}
197
+                            defaultHomeData={this.defaultHomeData}
198
+                        />
196 199
                     </NavigationContainer>
197 200
                 </PaperProvider>
198 201
             );

+ 0
- 55
src/components/Animations/AnimatedFocusView.js View File

@@ -1,55 +0,0 @@
1
-// @flow
2
-
3
-import * as React from 'react';
4
-import * as Animatable from "react-native-animatable";
5
-import {CommonActions} from "@react-navigation/native";
6
-import {StackNavigationProp} from "@react-navigation/stack";
7
-
8
-type Props = {
9
-    navigation: StackNavigationProp,
10
-    route: { params?: any, ... },
11
-    children: React.Node
12
-}
13
-
14
-export default class AnimatedFocusView extends React.Component<Props> {
15
-
16
-    ref: { current: null | Animatable.View };
17
-
18
-    constructor() {
19
-        super();
20
-        this.ref = React.createRef();
21
-    }
22
-
23
-    componentDidMount() {
24
-        this.props.navigation.addListener('focus', this.onScreenFocus);
25
-    }
26
-
27
-    onScreenFocus = () => {
28
-        if (this.props.route.params != null) {
29
-            if (this.props.route.params.animationDir && this.ref.current) {
30
-                if (this.props.route.params.animationDir === "right")
31
-                    this.ref.current.fadeInRight(300);
32
-                else
33
-                    this.ref.current.fadeInLeft(300);
34
-                // reset params to prevent infinite loop
35
-                this.props.navigation.dispatch(CommonActions.setParams({animationDir: null}));
36
-            }
37
-        }
38
-
39
-    };
40
-
41
-    render() {
42
-        return (
43
-            <Animatable.View
44
-                ref={this.ref}
45
-                style={{
46
-                    width: "100%",
47
-                    height: "100%",
48
-                }}
49
-                useNativeDriver
50
-            >
51
-                {this.props.children}
52
-            </Animatable.View>
53
-        );
54
-    }
55
-}

+ 17
- 19
src/components/Sidebar/Sidebar.js View File

@@ -7,18 +7,19 @@ import {TouchableRipple} from "react-native-paper";
7 7
 import ConnectionManager from "../../managers/ConnectionManager";
8 8
 import LogoutDialog from "../Amicale/LogoutDialog";
9 9
 import SideBarSection from "./SideBarSection";
10
+import {DrawerNavigationProp} from "@react-navigation/drawer";
10 11
 
11 12
 const deviceWidth = Dimensions.get("window").width;
12 13
 
13 14
 type Props = {
14
-    navigation: Object,
15
+    navigation: DrawerNavigationProp,
16
+    state: {[key: string] : any},
15 17
     theme?: Object,
16 18
 };
17 19
 
18 20
 type State = {
19 21
     isLoggedIn: boolean,
20 22
     dialogVisible: boolean,
21
-    activeRoute: string;
22 23
 };
23 24
 
24 25
 /**
@@ -27,7 +28,7 @@ type State = {
27 28
 class SideBar extends React.Component<Props, State> {
28 29
 
29 30
     dataSet: Array<Object>;
30
-
31
+    activeRoute: string;
31 32
     /**
32 33
      * Generate the dataset
33 34
      *
@@ -35,6 +36,7 @@ class SideBar extends React.Component<Props, State> {
35 36
      */
36 37
     constructor(props: Props) {
37 38
         super(props);
39
+        this.activeRoute = 'main';
38 40
         // Dataset used to render the drawer
39 41
         const mainData = [
40 42
             {
@@ -179,27 +181,23 @@ class SideBar extends React.Component<Props, State> {
179 181
             },
180 182
         ];
181 183
         ConnectionManager.getInstance().addLoginStateListener(this.onLoginStateChange);
182
-        this.props.navigation.addListener('state', this.onRouteChange);
183 184
         this.state = {
184 185
             isLoggedIn: ConnectionManager.getInstance().isLoggedIn(),
185 186
             dialogVisible: false,
186
-            activeRoute: 'Main',
187 187
         };
188 188
     }
189 189
 
190
-    onRouteChange = (event: Object) => {
191
-        try {
192
-            const state = event.data.state.routes[0].state; // Get the Drawer's state if it exists
193
-            // Get the current route name. This will only show Drawer routes.
194
-            // Tabbar routes will be shown as 'Main'
195
-            const routeName = state.routeNames[state.index];
196
-            if (this.state.activeRoute !== routeName)
197
-                this.setState({activeRoute: routeName});
198
-        } catch (e) {
199
-            this.setState({activeRoute: 'Main'});
200
-        }
190
+    shouldComponentUpdate(nextProps: Props, nextState: State): boolean {
191
+        const nextNavigationState = nextProps.state;
192
+        const nextRoute = nextNavigationState.routes[nextNavigationState.index].name;
201 193
 
202
-    };
194
+        const currentNavigationState = this.props.state;
195
+        const currentRoute = currentNavigationState.routes[currentNavigationState.index].name;
196
+
197
+        this.activeRoute = nextRoute;
198
+        return (nextState !== this.state)
199
+            || (nextRoute !== currentRoute);
200
+    }
203 201
 
204 202
     showDisconnectDialog = () => this.setState({dialogVisible: true});
205 203
 
@@ -217,7 +215,7 @@ class SideBar extends React.Component<Props, State> {
217 215
         return <SideBarSection
218 216
             {...this.props}
219 217
             listKey={item.key}
220
-            activeRoute={this.state.activeRoute}
218
+            activeRoute={this.activeRoute}
221 219
             isLoggedIn={this.state.isLoggedIn}
222 220
             sectionName={item.name}
223 221
             startOpen={item.startOpen}
@@ -239,7 +237,7 @@ class SideBar extends React.Component<Props, State> {
239 237
                 {/*$FlowFixMe*/}
240 238
                 <FlatList
241 239
                     data={this.dataSet}
242
-                    extraData={this.state.isLoggedIn.toString() + this.state.activeRoute}
240
+                    extraData={this.state.isLoggedIn.toString() + this.activeRoute}
243 241
                     renderItem={this.getRenderItem}
244 242
                 />
245 243
                 <LogoutDialog

+ 1
- 4
src/components/Tabbar/CustomTabBar.js View File

@@ -61,10 +61,7 @@ class CustomTabBar extends React.Component<Props, State> {
61 61
         });
62 62
         if (currentIndex !== destIndex && !event.defaultPrevented) {
63 63
             this.state.translateY = new Animated.Value(0);
64
-            this.props.navigation.navigate(route.name, {
65
-                screen: 'index',
66
-                params: {animationDir: currentIndex < destIndex ? "right" : "left"}
67
-            });
64
+            this.props.navigation.navigate(route.name);
68 65
         }
69 66
     }
70 67
 

+ 4
- 1
src/navigation/DrawerNavigator.js View File

@@ -541,7 +541,10 @@ export default class DrawerNavigator extends React.Component<Props> {
541 541
         this.createTabNavigator = () => <TabNavigator {...props}/>
542 542
     }
543 543
 
544
-    getDrawerContent = (props: { navigation: DrawerNavigationProp }) => <Sidebar {...props}/>
544
+    getDrawerContent = (props: {
545
+        navigation: DrawerNavigationProp,
546
+        state: {[key: string] : any}
547
+    }) => <Sidebar {...props}/>
545 548
 
546 549
     render() {
547 550
         return (

+ 6
- 12
src/screens/Home/HomeScreen.js View File

@@ -15,9 +15,9 @@ import ConnectionManager from "../../managers/ConnectionManager";
15 15
 import {CommonActions} from '@react-navigation/native';
16 16
 import MaterialHeaderButtons, {Item} from "../../components/Overrides/CustomHeaderButton";
17 17
 import AnimatedFAB from "../../components/Animations/AnimatedFAB";
18
-import AnimatedFocusView from "../../components/Animations/AnimatedFocusView";
19 18
 import {StackNavigationProp} from "@react-navigation/stack";
20 19
 import type {CustomTheme} from "../../managers/ThemeManager";
20
+import {View} from "react-native-animatable";
21 21
 // import DATA from "../dashboard_data.json";
22 22
 
23 23
 
@@ -166,17 +166,11 @@ class HomeScreen extends React.Component<Props> {
166 166
     };
167 167
 
168 168
     onProxiwashClick = () => {
169
-        this.props.navigation.navigate("proxiwash", {
170
-            screen: 'index',
171
-            params: {animationDir: "right"} // Play tab animation
172
-        });
169
+        this.props.navigation.navigate("proxiwash");
173 170
     };
174 171
 
175 172
     onProximoClick = () => {
176
-        this.props.navigation.navigate("proximo", {
177
-            screen: 'index',
178
-            params: {animationDir: "left"} // Play tab animation
179
-        });
173
+        this.props.navigation.navigate("proximo");
180 174
     };
181 175
 
182 176
     onTutorInsaClick = () => this.props.navigation.navigate('tutorinsa');
@@ -513,8 +507,8 @@ class HomeScreen extends React.Component<Props> {
513 507
 
514 508
     render() {
515 509
         return (
516
-            <AnimatedFocusView
517
-                {...this.props}
510
+            <View
511
+                style={{flex: 1}}
518 512
             >
519 513
                 <WebSectionList
520 514
                     {...this.props}
@@ -532,7 +526,7 @@ class HomeScreen extends React.Component<Props> {
532 526
                     icon="qrcode-scan"
533 527
                     onPress={this.openScanner}
534 528
                 />
535
-            </AnimatedFocusView>
529
+            </View>
536 530
         );
537 531
     }
538 532
 }

+ 3
- 4
src/screens/Planex/PlanexScreen.js View File

@@ -14,7 +14,6 @@ import DateManager from "../../managers/DateManager";
14 14
 import AnimatedBottomBar from "../../components/Animations/AnimatedBottomBar";
15 15
 import {CommonActions} from "@react-navigation/native";
16 16
 import ErrorView from "../../components/Screens/ErrorView";
17
-import AnimatedFocusView from "../../components/Animations/AnimatedFocusView";
18 17
 
19 18
 type Props = {
20 19
     navigation: Object,
@@ -300,8 +299,8 @@ class PlanexScreen extends React.Component<Props, State> {
300 299
     render() {
301 300
         const {containerPaddingTop} = this.props.collapsibleStack;
302 301
         return (
303
-            <AnimatedFocusView
304
-                {...this.props}
302
+            <View
303
+                style={{flex: 1}}
305 304
             >
306 305
                 <Banner
307 306
                     style={{
@@ -340,7 +339,7 @@ class PlanexScreen extends React.Component<Props, State> {
340 339
                     onPress={this.sendMessage}
341 340
                     seekAttention={this.state.currentGroup.id === -1}
342 341
                 />
343
-            </AnimatedFocusView>
342
+            </View>
344 343
         );
345 344
     }
346 345
 }

+ 27
- 32
src/screens/Planning/PlanningScreen.js View File

@@ -14,7 +14,6 @@ import {
14 14
 } from '../../utils/Planning';
15 15
 import {Avatar, Divider, List} from 'react-native-paper';
16 16
 import CustomAgenda from "../../components/Overrides/CustomAgenda";
17
-import AnimatedFocusView from "../../components/Animations/AnimatedFocusView";
18 17
 
19 18
 LocaleConfig.locales['fr'] = {
20 19
     monthNames: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
@@ -231,38 +230,34 @@ class PlanningScreen extends React.Component<Props, State> {
231 230
     render() {
232 231
         // console.log("rendering PlanningScreen");
233 232
         return (
234
-            <AnimatedFocusView
233
+            <CustomAgenda
235 234
                 {...this.props}
236
-            >
237
-                <CustomAgenda
238
-                    {...this.props}
239
-                    // the list of items that have to be displayed in agenda. If you want to render item as empty date
240
-                    // the value of date key kas to be an empty array []. If there exists no value for date key it is
241
-                    // considered that the date in question is not yet loaded
242
-                    items={this.state.agendaItems}
243
-                    // initially selected day
244
-                    selected={this.currentDate}
245
-                    // Minimum date that can be selected, dates before minDate will be grayed out. Default = undefined
246
-                    minDate={this.currentDate}
247
-                    // Max amount of months allowed to scroll to the past. Default = 50
248
-                    pastScrollRange={1}
249
-                    // Max amount of months allowed to scroll to the future. Default = 50
250
-                    futureScrollRange={AGENDA_MONTH_SPAN}
251
-                    // If provided, a standard RefreshControl will be added for "Pull to Refresh" functionality. Make sure to also set the refreshing prop correctly.
252
-                    onRefresh={this.onRefresh}
253
-                    // callback that fires when the calendar is opened or closed
254
-                    onCalendarToggled={this.onCalendarToggled}
255
-                    // Set this true while waiting for new data from a refresh
256
-                    refreshing={this.state.refreshing}
257
-                    renderItem={this.getRenderItem}
258
-                    renderEmptyDate={this.getRenderEmptyDate}
259
-                    rowHasChanged={this.rowHasChanged}
260
-                    // If firstDay=1 week starts from Monday. Note that dayNames and dayNamesShort should still start from Sunday.
261
-                    firstDay={1}
262
-                    // ref to this agenda in order to handle back button event
263
-                    onRef={this.onAgendaRef}
264
-                />
265
-            </AnimatedFocusView>
235
+                // the list of items that have to be displayed in agenda. If you want to render item as empty date
236
+                // the value of date key kas to be an empty array []. If there exists no value for date key it is
237
+                // considered that the date in question is not yet loaded
238
+                items={this.state.agendaItems}
239
+                // initially selected day
240
+                selected={this.currentDate}
241
+                // Minimum date that can be selected, dates before minDate will be grayed out. Default = undefined
242
+                minDate={this.currentDate}
243
+                // Max amount of months allowed to scroll to the past. Default = 50
244
+                pastScrollRange={1}
245
+                // Max amount of months allowed to scroll to the future. Default = 50
246
+                futureScrollRange={AGENDA_MONTH_SPAN}
247
+                // If provided, a standard RefreshControl will be added for "Pull to Refresh" functionality. Make sure to also set the refreshing prop correctly.
248
+                onRefresh={this.onRefresh}
249
+                // callback that fires when the calendar is opened or closed
250
+                onCalendarToggled={this.onCalendarToggled}
251
+                // Set this true while waiting for new data from a refresh
252
+                refreshing={this.state.refreshing}
253
+                renderItem={this.getRenderItem}
254
+                renderEmptyDate={this.getRenderEmptyDate}
255
+                rowHasChanged={this.rowHasChanged}
256
+                // If firstDay=1 week starts from Monday. Note that dayNames and dayNamesShort should still start from Sunday.
257
+                firstDay={1}
258
+                // ref to this agenda in order to handle back button event
259
+                onRef={this.onAgendaRef}
260
+            />
266 261
         );
267 262
     }
268 263
 }

+ 7
- 12
src/screens/Proximo/ProximoMainScreen.js View File

@@ -6,7 +6,6 @@ import i18n from "i18n-js";
6 6
 import WebSectionList from "../../components/Screens/WebSectionList";
7 7
 import {List, withTheme} from 'react-native-paper';
8 8
 import MaterialHeaderButtons, {Item} from "../../components/Overrides/CustomHeaderButton";
9
-import AnimatedFocusView from "../../components/Animations/AnimatedFocusView";
10 9
 
11 10
 const DATA_URL = "https://etud.insa-toulouse.fr/~proximo/data/stock-v2.json";
12 11
 const LIST_ITEM_HEIGHT = 84;
@@ -234,17 +233,13 @@ class ProximoMainScreen extends React.Component<Props, State> {
234 233
     render() {
235 234
         const nav = this.props.navigation;
236 235
         return (
237
-            <AnimatedFocusView
238
-                {...this.props}
239
-            >
240
-                <WebSectionList
241
-                    createDataset={this.createDataset}
242
-                    navigation={nav}
243
-                    autoRefreshTime={0}
244
-                    refreshOnFocus={false}
245
-                    fetchUrl={DATA_URL}
246
-                    renderItem={this.getRenderItem}/>
247
-            </AnimatedFocusView>
236
+            <WebSectionList
237
+                createDataset={this.createDataset}
238
+                navigation={nav}
239
+                autoRefreshTime={0}
240
+                refreshOnFocus={false}
241
+                fetchUrl={DATA_URL}
242
+                renderItem={this.getRenderItem}/>
248 243
         );
249 244
     }
250 245
 }

+ 5
- 6
src/screens/Proxiwash/ProxiwashScreen.js View File

@@ -15,7 +15,6 @@ import AprilFoolsManager from "../../managers/AprilFoolsManager";
15 15
 import MaterialHeaderButtons, {Item} from "../../components/Overrides/CustomHeaderButton";
16 16
 import ProxiwashSectionHeader from "../../components/Lists/Proxiwash/ProxiwashSectionHeader";
17 17
 import {withCollapsible} from "../../utils/withCollapsible";
18
-import AnimatedFocusView from "../../components/Animations/AnimatedFocusView";
19 18
 
20 19
 const DATA_URL = "https://etud.insa-toulouse.fr/~amicale_app/washinsa/washinsa.json";
21 20
 
@@ -422,13 +421,13 @@ class ProxiwashScreen extends React.Component<Props, State> {
422 421
         const nav = this.props.navigation;
423 422
         const {containerPaddingTop} = this.props.collapsibleStack;
424 423
         return (
425
-            <AnimatedFocusView
426
-                {...this.props}
424
+            <View
425
+                style={{flex: 1}}
427 426
             >
428 427
                 <Banner
429 428
                     style={{
430
-                    marginTop: this.state.bannerVisible ? containerPaddingTop : 0,
431
-                }}
429
+                        marginTop: this.state.bannerVisible ? containerPaddingTop : 0,
430
+                    }}
432 431
                     visible={this.state.bannerVisible}
433 432
                     actions={[
434 433
                         {
@@ -455,7 +454,7 @@ class ProxiwashScreen extends React.Component<Props, State> {
455 454
                     autoRefreshTime={REFRESH_TIME}
456 455
                     refreshOnFocus={true}
457 456
                     updateData={this.state.machinesWatched.length}/>
458
-            </AnimatedFocusView>
457
+            </View>
459 458
         );
460 459
     }
461 460
 }

Loading…
Cancel
Save