Browse Source

Merge branch 'dev'

keplyx 4 years ago
parent
commit
08f98caf30

+ 2
- 9
App.js View File

@@ -1,10 +1,9 @@
1 1
 // @flow
2 2
 
3 3
 import * as React from 'react';
4
-import {StatusBar, Platform} from 'react-native';
4
+import {Platform, StatusBar} from 'react-native';
5 5
 import {Root, StyleProvider} from 'native-base';
6 6
 import {createAppContainerWithInitialRoute} from './navigation/AppNavigator';
7
-import ThemeManager from './utils/ThemeManager';
8 7
 import LocaleManager from './utils/LocaleManager';
9 8
 import * as Font from 'expo-font';
10 9
 import {clearThemeCache} from 'native-base-shoutem-theme';
@@ -12,6 +11,7 @@ import AsyncStorageManager from "./utils/AsyncStorageManager";
12 11
 import CustomIntroSlider from "./components/CustomIntroSlider";
13 12
 import {AppLoading} from 'expo';
14 13
 import NotificationsManager from "./utils/NotificationsManager";
14
+import ThemeManager from './utils/ThemeManager';
15 15
 
16 16
 type Props = {};
17 17
 
@@ -49,12 +49,9 @@ export default class App extends React.Component<Props, State> {
49 49
 
50 50
     setupStatusBar() {
51 51
         if (Platform.OS === 'ios') {
52
-            console.log(ThemeManager.getNightMode());
53 52
             if (ThemeManager.getNightMode()) {
54
-                console.log('setting light mode');
55 53
                 StatusBar.setBarStyle('light-content', true);
56 54
             } else {
57
-                console.log('setting dark mode');
58 55
                 StatusBar.setBarStyle('dark-content', true);
59 56
             }
60 57
         }
@@ -73,7 +70,6 @@ export default class App extends React.Component<Props, State> {
73 70
     }
74 71
 
75 72
     async loadAssetsAsync() {
76
-        console.log('Starting loading assets...');
77 73
         // Wait for custom fonts to be loaded before showing the app
78 74
         await Font.loadAsync({
79 75
             'Roboto': require('native-base/Fonts/Roboto.ttf'),
@@ -83,18 +79,15 @@ export default class App extends React.Component<Props, State> {
83 79
         await AsyncStorageManager.getInstance().loadPreferences();
84 80
         ThemeManager.getInstance().setUpdateThemeCallback(() => this.updateTheme());
85 81
         await NotificationsManager.initExpoToken();
86
-        // console.log(AsyncStorageManager.getInstance().preferences.expoToken.current);
87 82
     }
88 83
 
89 84
     onLoadFinished() {
90 85
         // Only show intro if this is the first time starting the app
91
-        console.log('Finished loading');
92 86
         this.setState({
93 87
             isLoading: false,
94 88
             currentTheme: ThemeManager.getCurrentTheme(),
95 89
             showIntro: AsyncStorageManager.getInstance().preferences.showIntro.current === '1',
96 90
             showUpdate: AsyncStorageManager.getInstance().preferences.showUpdate5.current === '1'
97
-            // showIntro: true
98 91
         });
99 92
         // Status bar goes dark if set too fast
100 93
         setTimeout(this.setupStatusBar,

+ 9
- 0
Changelog.md View File

@@ -2,6 +2,15 @@
2 2
 
3 3
 Pensez à garder l'appli à jour pour profiter des dernières fonctionnalités !
4 4
 
5
+ - **v1.5.0** - _05/02/2020_
6
+    - Amélioration des performances de l'application
7
+    - Amélioration du menu gauche
8
+    - Ajout d'animations au changement d'écran
9
+    - Affichage de l'événement de l'accueil directement au clic, au lieu de juste amener sur la liste
10
+    - _Notes de développement :_
11
+        - Passage de React Navigation 3 à 4
12
+        - Mise à jour d'autres librairies
13
+
5 14
  - **v1.4.0** - _01/02/2020_
6 15
     - Correction d'un crash lors du rafraichissement de planex
7 16
     - Correction de bugs divers

+ 2
- 2
app.json View File

@@ -10,7 +10,7 @@
10 10
       "android",
11 11
       "web"
12 12
     ],
13
-    "version": "1.4.0",
13
+    "version": "1.5.0",
14 14
     "orientation": "portrait",
15 15
     "primaryColor": "#be1522",
16 16
     "icon": "./assets/android.icon.png",
@@ -36,7 +36,7 @@
36 36
     },
37 37
     "android": {
38 38
       "package": "fr.amicaleinsat.application",
39
-      "versionCode": 12,
39
+      "versionCode": 13,
40 40
       "icon": "./assets/android.icon.png",
41 41
       "adaptiveIcon": {
42 42
         "foregroundImage": "./assets/android.adaptive-icon.png",

+ 5
- 0
babel.config.js View File

@@ -2,5 +2,10 @@ module.exports = function(api) {
2 2
   api.cache(true);
3 3
   return {
4 4
     presets: ['babel-preset-expo'],
5
+    env: {
6
+      production: {
7
+        plugins: ['react-native-paper/babel'],
8
+      },
9
+    },
5 10
   };
6 11
 };

+ 7
- 28
components/BaseContainer.js View File

@@ -3,7 +3,6 @@
3 3
 import * as React from 'react';
4 4
 import {Container} from "native-base";
5 5
 import CustomHeader from "./CustomHeader";
6
-import CustomSideMenu from "./CustomSideMenu";
7 6
 import CustomMaterialIcon from "./CustomMaterialIcon";
8 7
 import {Platform, StatusBar, View} from "react-native";
9 8
 import ThemeManager from "../utils/ThemeManager";
@@ -15,6 +14,7 @@ import {NavigationActions} from "react-navigation";
15 14
 type Props = {
16 15
     navigation: Object,
17 16
     headerTitle: string,
17
+    headerSubtitle: string,
18 18
     headerRightButton: React.Node,
19 19
     children: React.Node,
20 20
     hasTabs: boolean,
@@ -25,7 +25,6 @@ type Props = {
25 25
 }
26 26
 
27 27
 type State = {
28
-    isOpen: boolean,
29 28
     isHeaderVisible: boolean
30 29
 }
31 30
 
@@ -39,24 +38,17 @@ export default class BaseContainer extends React.Component<Props, State> {
39 38
         hasSideMenu: true,
40 39
         enableRotation: false,
41 40
         hideHeaderOnLandscape: false,
41
+        headerSubtitle: '',
42 42
     };
43 43
     willBlurSubscription: function;
44 44
     willFocusSubscription: function;
45 45
     state = {
46
-        isOpen: false,
47 46
         isHeaderVisible: true,
48 47
     };
49 48
 
50 49
     toggle() {
51
-        this.setState({
52
-            isOpen: !this.state.isOpen,
53
-        });
50
+        this.props.navigation.toggleDrawer();
54 51
     }
55
-
56
-    updateMenuState(isOpen: boolean) {
57
-        this.setState({isOpen});
58
-    }
59
-
60 52
     /**
61 53
      * Register for blur event to close side menu on screen change
62 54
      */
@@ -87,7 +79,6 @@ export default class BaseContainer extends React.Component<Props, State> {
87 79
             () => {
88 80
                 if (this.props.enableRotation)
89 81
                     ScreenOrientation.lockAsync(ScreenOrientation.Orientation.PORTRAIT);
90
-                this.setState({isOpen: false});
91 82
             }
92 83
         );
93 84
     }
@@ -107,7 +98,9 @@ export default class BaseContainer extends React.Component<Props, State> {
107 98
             <Container>
108 99
                 {this.state.isHeaderVisible ?
109 100
                     <CustomHeader
110
-                        navigation={this.props.navigation} title={this.props.headerTitle}
101
+                        navigation={this.props.navigation}
102
+                        title={this.props.headerTitle}
103
+                        subtitle={this.props.headerSubtitle}
111 104
                         leftButton={
112 105
                             <Touchable
113 106
                                 style={{padding: 6}}
@@ -128,20 +121,6 @@ export default class BaseContainer extends React.Component<Props, State> {
128 121
 
129 122
 
130 123
     render() {
131
-        return (
132
-            <View style={{
133
-                backgroundColor: ThemeManager.getCurrentThemeVariables().sideMenuBgColor,
134
-                width: '100%',
135
-                height: '100%'
136
-            }}>
137
-                {this.props.hasSideMenu ?
138
-                    <CustomSideMenu
139
-                        navigation={this.props.navigation} isOpen={this.state.isOpen}
140
-                        onChange={(isOpen) => this.updateMenuState(isOpen)}>
141
-                        {this.getMainContainer()}
142
-                    </CustomSideMenu> :
143
-                    this.getMainContainer()}
144
-            </View>
145
-        );
124
+        return (this.getMainContainer());
146 125
     }
147 126
 }

+ 41
- 25
components/CustomHeader.js View File

@@ -1,13 +1,14 @@
1 1
 // @flow
2 2
 
3 3
 import * as React from "react";
4
-import {Body, Header, Input, Item, Left, Right, Title} from "native-base";
4
+import {Body, Header, Input, Item, Left, Right, Subtitle, Title} from "native-base";
5 5
 import {Platform, StyleSheet, View} from "react-native";
6 6
 import {getStatusBarHeight} from "react-native-status-bar-height";
7 7
 import Touchable from 'react-native-platform-touchable';
8 8
 import ThemeManager from "../utils/ThemeManager";
9 9
 import CustomMaterialIcon from "./CustomMaterialIcon";
10 10
 import i18n from "i18n-js";
11
+import {NavigationActions} from 'react-navigation';
11 12
 
12 13
 type Props = {
13 14
     hasBackButton: boolean,
@@ -17,6 +18,7 @@ type Props = {
17 18
     leftButton: React.Node,
18 19
     rightButton: React.Node,
19 20
     title: string,
21
+    subtitle: string,
20 22
     navigation: Object,
21 23
     hasTabs: boolean,
22 24
 };
@@ -37,6 +39,7 @@ export default class CustomHeader extends React.Component<Props> {
37 39
         searchCallback: () => null,
38 40
         shouldFocusSearchBar: false,
39 41
         title: '',
42
+        subtitle: '',
40 43
         leftButton: <View/>,
41 44
         rightButton: <View/>,
42 45
         hasTabs: false,
@@ -51,23 +54,39 @@ export default class CustomHeader extends React.Component<Props> {
51 54
 
52 55
     getSearchBar() {
53 56
         return (
54
-            <Item
55
-                style={{
56
-                    width: '100%',
57
-                    marginBottom: 7
57
+            <Body>
58
+                <Item
59
+                    style={{
60
+                        width: '100%',
61
+                        marginBottom: 7
62
+                    }}>
63
+                    <CustomMaterialIcon
64
+                        icon={'magnify'}
65
+                        color={ThemeManager.getCurrentThemeVariables().toolbarBtnColor}/>
66
+                    <Input
67
+                        ref="searchInput"
68
+                        placeholder={i18n.t('proximoScreen.search')}
69
+                        placeholderTextColor={ThemeManager.getCurrentThemeVariables().toolbarPlaceholderColor}
70
+                        onChangeText={(text) => this.props.searchCallback(text)}/>
71
+                </Item>
72
+            </Body>
73
+        );
74
+    }
75
+
76
+    getHeaderTitle() {
77
+        return (
78
+            <Body>
79
+                <Title style={{
80
+                    color: ThemeManager.getCurrentThemeVariables().toolbarTextColor
58 81
                 }}>
59
-                <CustomMaterialIcon
60
-                    icon={'magnify'}
61
-                    color={ThemeManager.getCurrentThemeVariables().toolbarBtnColor}/>
62
-                <Input
63
-                    ref="searchInput"
64
-                    placeholder={i18n.t('proximoScreen.search')}
65
-                    placeholderTextColor={ThemeManager.getCurrentThemeVariables().toolbarPlaceholderColor}
66
-                    onChangeText={(text) => this.props.searchCallback(text)}/>
67
-            </Item>
82
+                    {this.props.title}
83
+                </Title>
84
+                {this.props.subtitle !== '' ? <Subtitle>{this.props.subtitle}</Subtitle> : null}
85
+            </Body>
68 86
         );
69 87
     }
70 88
 
89
+
71 90
     render() {
72 91
         let button;
73 92
         // Does the app have a back button or a burger menu ?
@@ -75,10 +94,13 @@ export default class CustomHeader extends React.Component<Props> {
75 94
             button =
76 95
                 <Touchable
77 96
                     style={{padding: 6}}
78
-                    onPress={() => this.props.navigation.goBack()}>
97
+                    onPress={() => {
98
+                        const backAction = NavigationActions.back();
99
+                        this.props.navigation.dispatch(backAction);
100
+                    }}>
79 101
                     <CustomMaterialIcon
80 102
                         color={Platform.OS === 'ios' ? ThemeManager.getCurrentThemeVariables().brandPrimary : "#fff"}
81
-                        icon="arrow-left"/>
103
+                        icon={Platform.OS === 'ios' ? 'chevron-left' : "arrow-left"}/>
82 104
                 </Touchable>;
83 105
         else
84 106
             button = this.props.leftButton;
@@ -89,14 +111,9 @@ export default class CustomHeader extends React.Component<Props> {
89 111
                 <Left style={{flex: 0}}>
90 112
                     {button}
91 113
                 </Left>
92
-                <Body>
93
-                    {this.props.hasSearchField ?
94
-                        this.getSearchBar() :
95
-                        <Title style={{
96
-                            paddingLeft: 10,
97
-                            color: ThemeManager.getCurrentThemeVariables().toolbarTextColor
98
-                        }}>{this.props.title}</Title>}
99
-                </Body>
114
+                {this.props.hasSearchField ?
115
+                    this.getSearchBar() :
116
+                    this.getHeaderTitle()}
100 117
                 <Right style={{flex: this.props.hasSearchField ? 0 : 1}}>
101 118
                     {this.props.rightButton}
102 119
                 </Right>
@@ -104,7 +121,6 @@ export default class CustomHeader extends React.Component<Props> {
104 121
     }
105 122
 };
106 123
 
107
-
108 124
 // Fix header in status bar on Android
109 125
 const styles = StyleSheet.create({
110 126
     header: {

+ 0
- 48
components/CustomSideMenu.js View File

@@ -1,48 +0,0 @@
1
-// @flow
2
-
3
-import * as React from 'react';
4
-import SideMenu from "react-native-side-menu";
5
-import SideBar from "./Sidebar";
6
-import {View} from "react-native";
7
-
8
-
9
-type Props = {
10
-    navigation: Object,
11
-    children: React.Node,
12
-    isOpen: boolean,
13
-    onChange: Function,
14
-}
15
-
16
-type State = {
17
-    shouldShowMenu: boolean, // Prevent menu from showing in transitions between tabs
18
-}
19
-
20
-export default class CustomSideMenu extends React.Component<Props, State> {
21
-
22
-    state = {
23
-        shouldShowMenu: this.props.isOpen,
24
-    };
25
-
26
-    // Stop the side menu from being shown while tab transition is playing
27
-    // => Hide the menu when behind the actual screen
28
-    onMenuMove(percent: number) {
29
-        if (percent <= 0)
30
-            this.setState({shouldShowMenu: false});
31
-        else if (this.state.shouldShowMenu === false)
32
-            this.setState({shouldShowMenu: true});
33
-    }
34
-
35
-    render() {
36
-        return (
37
-            <SideMenu menu={
38
-                this.state.shouldShowMenu ?
39
-                    <SideBar navigation={this.props.navigation}/>
40
-                    : <View/>}
41
-                      isOpen={this.props.isOpen}
42
-                      onChange={this.props.onChange}
43
-                      onSliding={(percent) => this.onMenuMove(percent)}>
44
-                {this.props.children}
45
-            </SideMenu>
46
-        );
47
-    }
48
-}

+ 3
- 45
navigation/AppNavigator.js View File

@@ -1,56 +1,14 @@
1 1
 // @flow
2 2
 
3
-import {createAppContainer, createStackNavigator} from 'react-navigation';
4
-import {createMaterialBottomTabNavigatorWithInitialRoute} from './MainTabNavigator';
5
-import SettingsScreen from '../screens/SettingsScreen';
6
-import AboutScreen from '../screens/About/AboutScreen';
7
-import ProximoListScreen from '../screens/Proximo/ProximoListScreen';
8
-import AboutDependenciesScreen from '../screens/About/AboutDependenciesScreen';
9
-import ProxiwashAboutScreen from '../screens/Proxiwash/ProxiwashAboutScreen';
10
-import ProximoAboutScreen from '../screens/Proximo/ProximoAboutScreen';
11
-import SelfMenuScreen from '../screens/SelfMenuScreen';
12
-import TutorInsaScreen from "../screens/Websites/TutorInsaScreen";
13
-import AmicaleScreen from "../screens/Websites/AmicaleScreen";
14
-import WiketudScreen from "../screens/Websites/WiketudScreen";
15
-import ElusEtudScreen from "../screens/Websites/ElusEtudScreen";
16
-import BlueMindScreen from "../screens/Websites/BlueMindScreen";
17
-import EntScreen from "../screens/Websites/EntScreen";
18
-import AvailableRoomScreen from "../screens/Websites/AvailableRoomScreen";
19
-import DebugScreen from '../screens/DebugScreen';
20
-import {fromRight} from "react-navigation-transitions";
3
+import {createAppContainer} from 'react-navigation';
4
+import {createDrawerNavigatorWithInitialRoute} from './DrawerNavigator';
21 5
 
22 6
 
23 7
 /**
24 8
  * Create a stack navigator using the drawer to handle navigation between screens
25 9
  */
26 10
 function createAppContainerWithInitialRoute(initialRoute: string) {
27
-    return createAppContainer(
28
-        createStackNavigator({
29
-                Main: createMaterialBottomTabNavigatorWithInitialRoute(initialRoute),
30
-                // Drawer: MainDrawerNavigator,
31
-                ProximoListScreen: {screen: ProximoListScreen},
32
-                SettingsScreen: {screen: SettingsScreen},
33
-                AboutScreen: {screen: AboutScreen},
34
-                AboutDependenciesScreen: {screen: AboutDependenciesScreen},
35
-                SelfMenuScreen: {screen: SelfMenuScreen},
36
-                TutorInsaScreen: {screen: TutorInsaScreen},
37
-                AmicaleScreen: {screen: AmicaleScreen},
38
-                WiketudScreen: {screen: WiketudScreen},
39
-                ElusEtudScreen: {screen: ElusEtudScreen},
40
-                BlueMindScreen: {screen: BlueMindScreen},
41
-                EntScreen: {screen: EntScreen},
42
-                AvailableRoomScreen: {screen: AvailableRoomScreen},
43
-                ProxiwashAboutScreen: {screen: ProxiwashAboutScreen},
44
-                ProximoAboutScreen: {screen: ProximoAboutScreen},
45
-                DebugScreen: {screen: DebugScreen},
46
-            },
47
-            {
48
-                initialRouteName: "Main",
49
-                mode: 'card',
50
-                headerMode: "none",
51
-                transitionConfig: () => fromRight(),
52
-            })
53
-    );
11
+    return createAppContainer(createDrawerNavigatorWithInitialRoute(initialRoute));
54 12
 }
55 13
 
56 14
 export {createAppContainerWithInitialRoute};

+ 79
- 0
navigation/DrawerNavigator.js View File

@@ -0,0 +1,79 @@
1
+// @flow
2
+
3
+import { createDrawerNavigator } from 'react-navigation-drawer';
4
+import {createMaterialBottomTabNavigatorWithInitialRoute} from './MainTabNavigator';
5
+import SettingsScreen from '../screens/SettingsScreen';
6
+import AboutScreen from '../screens/About/AboutScreen';
7
+import AboutDependenciesScreen from '../screens/About/AboutDependenciesScreen';
8
+import SelfMenuScreen from '../screens/SelfMenuScreen';
9
+import TutorInsaScreen from "../screens/Websites/TutorInsaScreen";
10
+import AmicaleScreen from "../screens/Websites/AmicaleScreen";
11
+import WiketudScreen from "../screens/Websites/WiketudScreen";
12
+import ElusEtudScreen from "../screens/Websites/ElusEtudScreen";
13
+import BlueMindScreen from "../screens/Websites/BlueMindScreen";
14
+import EntScreen from "../screens/Websites/EntScreen";
15
+import AvailableRoomScreen from "../screens/Websites/AvailableRoomScreen";
16
+import DebugScreen from '../screens/DebugScreen';
17
+import Sidebar from "../components/Sidebar";
18
+import {createStackNavigator, TransitionPresets} from "react-navigation-stack";
19
+
20
+const AboutStack = createStackNavigator({
21
+        AboutScreen: {screen: AboutScreen},
22
+        AboutDependenciesScreen: {screen: AboutDependenciesScreen},
23
+        DebugScreen: {screen: DebugScreen},
24
+    },
25
+    {
26
+        initialRouteName: "AboutScreen",
27
+        mode: 'card',
28
+        headerMode: "none",
29
+        defaultNavigationOptions: {
30
+            gestureEnabled: true,
31
+            cardOverlayEnabled: true,
32
+            ...TransitionPresets.SlideFromRightIOS,
33
+        },
34
+    });
35
+
36
+
37
+// Create a stack to use animations
38
+function createDrawerStackWithInitialRoute(initialRoute: string) {
39
+    return createStackNavigator({
40
+            Main: createMaterialBottomTabNavigatorWithInitialRoute(initialRoute),
41
+            SettingsScreen: {screen: SettingsScreen},
42
+            AboutScreen: AboutStack,
43
+            SelfMenuScreen: {screen: SelfMenuScreen},
44
+            TutorInsaScreen: {screen: TutorInsaScreen},
45
+            AmicaleScreen: {screen: AmicaleScreen},
46
+            WiketudScreen: {screen: WiketudScreen},
47
+            ElusEtudScreen: {screen: ElusEtudScreen},
48
+            BlueMindScreen: {screen: BlueMindScreen},
49
+            EntScreen: {screen: EntScreen},
50
+            AvailableRoomScreen: {screen: AvailableRoomScreen},
51
+        },
52
+        {
53
+            initialRouteName: "Main",
54
+            mode: 'card',
55
+            headerMode: "none",
56
+            defaultNavigationOptions: {
57
+                gestureEnabled: true,
58
+                cardOverlayEnabled: true,
59
+                ...TransitionPresets.SlideFromRightIOS,
60
+            },
61
+        });
62
+}
63
+
64
+/**
65
+ * Creates the drawer navigation stack
66
+ */
67
+function createDrawerNavigatorWithInitialRoute(initialRoute: string) {
68
+    return createDrawerNavigator({
69
+        Main: createDrawerStackWithInitialRoute(initialRoute),
70
+    }, {
71
+        contentComponent: Sidebar,
72
+        initialRouteName: 'Main',
73
+        backBehavior: 'initialRoute',
74
+        drawerType: 'front',
75
+        useNativeAnimations: true,
76
+    });
77
+}
78
+
79
+export {createDrawerNavigatorWithInitialRoute};

+ 75
- 4
navigation/MainTabNavigator.js View File

@@ -1,10 +1,15 @@
1 1
 import * as React from 'react';
2
+import {createStackNavigator, TransitionPresets} from 'react-navigation-stack';
2 3
 import {createMaterialBottomTabNavigator} from "react-navigation-material-bottom-tabs";
3 4
 
4 5
 import HomeScreen from '../screens/HomeScreen';
5 6
 import PlanningScreen from '../screens/PlanningScreen';
7
+import PlanningDisplayScreen from '../screens/PlanningDisplayScreen';
6 8
 import ProxiwashScreen from '../screens/Proxiwash/ProxiwashScreen';
9
+import ProxiwashAboutScreen from '../screens/Proxiwash/ProxiwashAboutScreen';
7 10
 import ProximoMainScreen from '../screens/Proximo/ProximoMainScreen';
11
+import ProximoListScreen from "../screens/Proximo/ProximoListScreen";
12
+import ProximoAboutScreen from "../screens/Proximo/ProximoAboutScreen";
8 13
 import PlanexScreen from '../screens/Websites/PlanexScreen';
9 14
 import CustomMaterialIcon from "../components/CustomMaterialIcon";
10 15
 import ThemeManager from "../utils/ThemeManager";
@@ -17,12 +22,78 @@ const TAB_ICONS = {
17 22
     Planex: 'timetable',
18 23
 };
19 24
 
25
+const ProximoStack = createStackNavigator({
26
+        ProximoMainScreen: {screen: ProximoMainScreen},
27
+        ProximoListScreen: {screen: ProximoListScreen},
28
+        ProximoAboutScreen: {
29
+            screen: ProximoAboutScreen,
30
+            navigationOptions: () => ({
31
+                ...TransitionPresets.ModalSlideFromBottomIOS,
32
+            }),
33
+        },
34
+    },
35
+    {
36
+        initialRouteName: "ProximoMainScreen",
37
+        mode: 'card',
38
+        headerMode: "none",
39
+        defaultNavigationOptions: {
40
+            gestureEnabled: true,
41
+            cardOverlayEnabled: true,
42
+            ...TransitionPresets.SlideFromRightIOS,
43
+        },
44
+    });
45
+
46
+const ProxiwashStack = createStackNavigator({
47
+        ProxiwashScreen: {screen: ProxiwashScreen},
48
+        ProxiwashAboutScreen: {screen: ProxiwashAboutScreen},
49
+    },
50
+    {
51
+        initialRouteName: "ProxiwashScreen",
52
+        mode: 'card',
53
+        headerMode: "none",
54
+        defaultNavigationOptions: {
55
+            gestureEnabled: true,
56
+            cardOverlayEnabled: true,
57
+            ...TransitionPresets.ModalSlideFromBottomIOS,
58
+        },
59
+    });
60
+
61
+const PlanningStack = createStackNavigator({
62
+        PlanningScreen: {screen: PlanningScreen},
63
+        PlanningDisplayScreen: {screen: PlanningDisplayScreen},
64
+    },
65
+    {
66
+        initialRouteName: "PlanningScreen",
67
+        mode: 'card',
68
+        headerMode: "none",
69
+        defaultNavigationOptions: {
70
+            gestureEnabled: true,
71
+            cardOverlayEnabled: true,
72
+            ...TransitionPresets.ModalSlideFromBottomIOS,
73
+        },
74
+    });
75
+
76
+const HomeStack = createStackNavigator({
77
+        HomeScreen: {screen: HomeScreen},
78
+        PlanningDisplayScreen: {screen: PlanningDisplayScreen},
79
+    },
80
+    {
81
+        initialRouteName: "HomeScreen",
82
+        mode: 'card',
83
+        headerMode: "none",
84
+        defaultNavigationOptions: {
85
+            gestureEnabled: true,
86
+            cardOverlayEnabled: true,
87
+            ...TransitionPresets.ModalSlideFromBottomIOS,
88
+        },
89
+    });
90
+
20 91
 function createMaterialBottomTabNavigatorWithInitialRoute(initialRoute: string) {
21 92
     return createMaterialBottomTabNavigator({
22
-        Home: {screen: HomeScreen},
23
-        Planning: {screen: PlanningScreen,},
24
-        Proxiwash: {screen: ProxiwashScreen,},
25
-        Proximo: {screen: ProximoMainScreen,},
93
+        Home: HomeStack,
94
+        Planning: PlanningStack,
95
+        Proxiwash: ProxiwashStack,
96
+        Proximo: ProximoStack,
26 97
         Planex: {
27 98
             screen: PlanexScreen,
28 99
             navigationOptions: ({navigation}) => {

+ 9
- 5
package.json View File

@@ -8,6 +8,7 @@
8 8
     "eject": "expo eject"
9 9
   },
10 10
   "dependencies": {
11
+    "@react-native-community/masked-view": "0.1.5",
11 12
     "expo": "^36.0.0",
12 13
     "expo-font": "~8.0.0",
13 14
     "expo-linear-gradient": "~8.0.0",
@@ -21,19 +22,22 @@
21 22
     "react-native": "https://github.com/expo/react-native/archive/sdk-36.0.1.tar.gz",
22 23
     "react-native-app-intro-slider": "^3.0.0",
23 24
     "react-native-autolink": "^1.8.1",
24
-    "react-native-calendars": "^1.212.0",
25
+    "react-native-calendars": "^1.260.0",
25 26
     "react-native-gesture-handler": "~1.5.0",
26
-    "react-native-material-menu": "^0.6.7",
27
+    "react-native-material-menu": "^1.0.0",
27 28
     "react-native-modalize": "^1.3.6",
28 29
     "react-native-paper": "^3.5.1",
29 30
     "react-native-platform-touchable": "^1.1.1",
31
+    "react-native-reanimated": "~1.4.0",
30 32
     "react-native-render-html": "^4.1.2",
33
+    "react-native-safe-area-context": "0.6.0",
31 34
     "react-native-screens": "2.0.0-alpha.12",
32
-    "react-native-side-menu": "^1.1.3",
33 35
     "react-native-status-bar-height": "^2.3.1",
34 36
     "react-native-webview": "7.4.3",
35
-    "react-navigation": "^3.13.0",
36
-    "react-navigation-material-bottom-tabs": "^1.1.1",
37
+    "react-navigation": "^4.1.0",
38
+    "react-navigation-drawer": "^2.3.3",
39
+    "react-navigation-material-bottom-tabs": "^2.1.5",
40
+    "react-navigation-stack": "^2.1.0",
37 41
     "react-navigation-transitions": "^1.0.12"
38 42
   },
39 43
   "devDependencies": {

+ 0
- 2
screens/About/AboutScreen.js View File

@@ -319,14 +319,12 @@ export default class AboutScreen extends React.Component<Props, State> {
319 319
 
320 320
     tryUnlockDebugMode() {
321 321
         this.debugTapCounter = this.debugTapCounter + 1;
322
-        console.log(this.debugTapCounter);
323 322
         if (this.debugTapCounter >= 4) {
324 323
             this.unlockDebugMode();
325 324
         }
326 325
     }
327 326
 
328 327
     unlockDebugMode() {
329
-        console.log('unlocked');
330 328
         this.setState({isDebugUnlocked: true});
331 329
         let key = AsyncStorageManager.getInstance().preferences.debugUnlocked.key;
332 330
         AsyncStorageManager.getInstance().savePref(key, '1');

+ 0
- 1
screens/DebugScreen.js View File

@@ -83,7 +83,6 @@ export default class DebugScreen extends React.Component<Props, State> {
83 83
 
84 84
     alertCurrentExpoToken() {
85 85
         let token = AsyncStorageManager.getInstance().preferences.expoToken.current;
86
-        console.log(token);
87 86
         Alert.alert(
88 87
             'Expo Token',
89 88
             token,

+ 6
- 1
screens/HomeScreen.js View File

@@ -310,7 +310,12 @@ export default class HomeScreen extends FetchedDataSectionList {
310 310
                 </Text>;
311 311
         } else
312 312
             subtitle = i18n.t('homeScreen.dashboard.todayEventsSubtitleNA');
313
-        let clickAction = () => this.props.navigation.navigate('Planning');
313
+        let clickAction = () => {
314
+            if (isAvailable)
315
+                this.props.navigation.navigate('PlanningDisplayScreen', {data: displayEvent});
316
+            else
317
+                this.props.navigation.navigate('PlanningScreen');
318
+        };
314 319
 
315 320
         let displayEvent = this.getDisplayEvent(futureEvents);
316 321
 

+ 69
- 0
screens/PlanningDisplayScreen.js View File

@@ -0,0 +1,69 @@
1
+// @flow
2
+
3
+import * as React from 'react';
4
+import {Image} from 'react-native';
5
+import {Container, Content, H1, H3, View} from 'native-base';
6
+import CustomHeader from "../components/CustomHeader";
7
+import ThemeManager from "../utils/ThemeManager";
8
+import HTML from "react-native-render-html";
9
+import {Linking} from "expo";
10
+import PlanningEventManager from '../utils/PlanningEventManager';
11
+import i18n from 'i18n-js';
12
+
13
+type Props = {
14
+    navigation: Object,
15
+};
16
+
17
+function openWebLink(link) {
18
+    Linking.openURL(link).catch((err) => console.error('Error opening link', err));
19
+}
20
+
21
+/**
22
+ * Class defining an about screen. This screen shows the user information about the app and it's author.
23
+ */
24
+export default class PlanningDisplayScreen extends React.Component<Props> {
25
+
26
+    render() {
27
+        const nav = this.props.navigation;
28
+        const displayData = nav.getParam('data', []);
29
+        return (
30
+            <Container>
31
+                <CustomHeader
32
+                    navigation={nav}
33
+                    title={displayData.title}
34
+                    subtitle={PlanningEventManager.getFormattedTime(displayData)}
35
+                    hasBackButton={true}/>
36
+                <Content padder>
37
+                    <H1>
38
+                        {displayData.title}
39
+                    </H1>
40
+                    <H3 style={{
41
+                        marginTop: 10,
42
+                        color: ThemeManager.getCurrentThemeVariables().listNoteColor
43
+                    }}>
44
+                        {PlanningEventManager.getFormattedTime(displayData)}
45
+                    </H3>
46
+                    {displayData.logo !== null ?
47
+                        <View style={{width: '100%', height: 300, marginTop: 20, marginBottom: 20}}>
48
+                            <Image style={{flex: 1, resizeMode: "contain"}}
49
+                                   source={{uri: displayData.logo}}/>
50
+                        </View>
51
+                        : <View/>}
52
+
53
+                    {displayData.description !== null ?
54
+                        // Surround description with div to allow text styling if the description is not html
55
+                        <HTML html={"<div>" + displayData.description + "</div>"}
56
+                              tagsStyles={{
57
+                                  p: {
58
+                                      color: ThemeManager.getCurrentThemeVariables().textColor,
59
+                                      fontSize: ThemeManager.getCurrentThemeVariables().fontSizeBase
60
+                                  },
61
+                                  div: {color: ThemeManager.getCurrentThemeVariables().textColor}
62
+                              }}
63
+                              onLinkPress={(event, link) => openWebLink(link)}/>
64
+                        : <View/>}
65
+                </Content>
66
+            </Container>
67
+        );
68
+    }
69
+}

+ 12
- 142
screens/PlanningScreen.js View File

@@ -1,18 +1,16 @@
1 1
 // @flow
2 2
 
3 3
 import * as React from 'react';
4
-import {BackHandler, Image, View} from 'react-native';
5
-import {Button, Content, H1, H3, Text} from 'native-base';
4
+import {BackHandler, Image} from 'react-native';
5
+import {H3, Text, View} from 'native-base';
6 6
 import i18n from "i18n-js";
7 7
 import ThemeManager from "../utils/ThemeManager";
8 8
 import {Linking} from "expo";
9 9
 import BaseContainer from "../components/BaseContainer";
10 10
 import {Agenda, LocaleConfig} from 'react-native-calendars';
11
-import HTML from 'react-native-render-html';
12 11
 import Touchable from 'react-native-platform-touchable';
13
-import {Modalize} from 'react-native-modalize';
14 12
 import WebDataManager from "../utils/WebDataManager";
15
-import CustomMaterialIcon from "../components/CustomMaterialIcon";
13
+import PlanningEventManager from '../utils/PlanningEventManager';
16 14
 
17 15
 LocaleConfig.locales['fr'] = {
18 16
     monthNames: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'],
@@ -28,7 +26,6 @@ type Props = {
28 26
 }
29 27
 
30 28
 type State = {
31
-    modalCurrentDisplayItem: Object,
32 29
     refreshing: boolean,
33 30
     agendaItems: Object,
34 31
     calendarShowing: boolean,
@@ -51,7 +48,6 @@ function openWebLink(link) {
51 48
  */
52 49
 export default class PlanningScreen extends React.Component<Props, State> {
53 50
 
54
-    modalRef: Modalize;
55 51
     agendaRef: Agenda;
56 52
     webDataManager: WebDataManager;
57 53
 
@@ -61,7 +57,6 @@ export default class PlanningScreen extends React.Component<Props, State> {
61 57
     didFocusSubscription: Function;
62 58
     willBlurSubscription: Function;
63 59
     state = {
64
-        modalCurrentDisplayItem: {},
65 60
         refreshing: false,
66 61
         agendaItems: {},
67 62
         calendarShowing: false,
@@ -69,7 +64,6 @@ export default class PlanningScreen extends React.Component<Props, State> {
69 64
 
70 65
     constructor(props: any) {
71 66
         super(props);
72
-        this.modalRef = React.createRef();
73 67
         this.webDataManager = new WebDataManager(FETCH_URL);
74 68
         this.didFocusSubscription = props.navigation.addListener(
75 69
             'didFocus',
@@ -131,72 +125,11 @@ export default class PlanningScreen extends React.Component<Props, State> {
131 125
         return daysOfYear;
132 126
     }
133 127
 
134
-    getModalHeader() {
135
-        return (
136
-            <View style={{marginBottom: 0}}>
137
-                <Button
138
-                    onPress={() => this.modalRef.current.close()}
139
-                    style={{
140
-                        marginTop: 50,
141
-                        marginLeft: 'auto',
142
-                    }}
143
-                    transparent>
144
-                    <CustomMaterialIcon icon={'close'}/>
145
-                </Button>
146
-            </View>
147
-        );
148
-    }
149
-
150
-    getModalContent() {
151
-        return (
152
-            <View style={{
153
-                flex: 1,
154
-                padding: 20
155
-            }}>
156
-                <H1>
157
-                    {this.state.modalCurrentDisplayItem.title}
158
-                </H1>
159
-                <H3 style={{
160
-                    marginTop: 10,
161
-                    color: ThemeManager.getCurrentThemeVariables().listNoteColor
162
-                }}>
163
-                    {this.getFormattedTime(this.state.modalCurrentDisplayItem)}
164
-                </H3>
165
-                <Content>
166
-                    {this.state.modalCurrentDisplayItem.logo !== null ?
167
-                        <View style={{width: '100%', height: 200, marginTop: 20, marginBottom: 20}}>
168
-                            <Image style={{flex: 1, resizeMode: "contain"}}
169
-                                   source={{uri: this.state.modalCurrentDisplayItem.logo}}/>
170
-                        </View>
171
-                        : <View/>}
172
-
173
-                    {this.state.modalCurrentDisplayItem.description !== null ?
174
-                        // Surround description with div to allow text styling if the description is not html
175
-                        <HTML html={"<div>" + this.state.modalCurrentDisplayItem.description + "</div>"}
176
-                              tagsStyles={{
177
-                                  p: {
178
-                                      color: ThemeManager.getCurrentThemeVariables().textColor,
179
-                                      fontSize: ThemeManager.getCurrentThemeVariables().fontSizeBase
180
-                                  },
181
-                                  div: {color: ThemeManager.getCurrentThemeVariables().textColor}
182
-                              }}
183
-                              onLinkPress={(event, link) => openWebLink(link)}/>
184
-                        : <View/>}
185
-                </Content>
186
-            </View>
187
-        );
188
-    }
189
-
190
-    showItemDetails(item: Object) {
191
-        this.setState({
192
-            modalCurrentDisplayItem: item,
193
-        });
194
-        if (this.modalRef.current) {
195
-            this.modalRef.current.open();
196
-        }
197
-    }
198
-
199 128
     getRenderItem(item: Object) {
129
+        let navData = {
130
+            data: item
131
+        };
132
+        const nav = this.props.navigation;
200 133
         return (
201 134
             <Touchable
202 135
                 style={{
@@ -205,7 +138,7 @@ export default class PlanningScreen extends React.Component<Props, State> {
205 138
                     marginRight: 10,
206 139
                     marginTop: 17,
207 140
                 }}
208
-                onPress={() => this.showItemDetails(item)}>
141
+                onPress={() => nav.navigate('PlanningDisplayScreen', navData)}>
209 142
                 <View style={{
210 143
                     padding: 10,
211 144
                     flex: 1,
@@ -219,7 +152,7 @@ export default class PlanningScreen extends React.Component<Props, State> {
219 152
                             marginTop: 5,
220 153
                             marginBottom: 10
221 154
                         }}>
222
-                            {this.getFormattedTime(item)}
155
+                            {PlanningEventManager.getFormattedTime(item)}
223 156
                         </Text>
224 157
                         <H3 style={{marginBottom: 10}}>{item.title}</H3>
225 158
                     </View>
@@ -296,8 +229,8 @@ export default class PlanningScreen extends React.Component<Props, State> {
296 229
     generateEventAgenda(eventList: Array<Object>) {
297 230
         let agendaItems = this.generateEmptyCalendar();
298 231
         for (let i = 0; i < eventList.length; i++) {
299
-            if (agendaItems[this.getEventStartDate(eventList[i])] !== undefined) {
300
-                this.pushEventInOrder(agendaItems, eventList[i], this.getEventStartDate(eventList[i]));
232
+            if (agendaItems[PlanningEventManager.getEventStartDate(eventList[i])] !== undefined) {
233
+                this.pushEventInOrder(agendaItems, eventList[i], PlanningEventManager.getEventStartDate(eventList[i]));
301 234
             }
302 235
         }
303 236
         this.setState({agendaItems: agendaItems})
@@ -308,7 +241,7 @@ export default class PlanningScreen extends React.Component<Props, State> {
308 241
             agendaItems[startDate].push(event);
309 242
         else {
310 243
             for (let i = 0; i < agendaItems[startDate].length; i++) {
311
-                if (this.isEventBefore(event, agendaItems[startDate][i])) {
244
+                if (PlanningEventManager.isEventBefore(event, agendaItems[startDate][i])) {
312 245
                     agendaItems[startDate].splice(i, 0, event);
313 246
                     break;
314 247
                 } else if (i === agendaItems[startDate].length - 1) {
@@ -319,65 +252,10 @@ export default class PlanningScreen extends React.Component<Props, State> {
319 252
         }
320 253
     }
321 254
 
322
-    isEventBefore(event1: Object, event2: Object) {
323
-        let date1 = new Date();
324
-        let date2 = new Date();
325
-        let timeArray = this.getEventStartTime(event1).split(":");
326
-        date1.setHours(parseInt(timeArray[0]), parseInt(timeArray[1]));
327
-        timeArray = this.getEventStartTime(event2).split(":");
328
-        date2.setHours(parseInt(timeArray[0]), parseInt(timeArray[1]));
329
-        return date1 < date2;
330
-    }
331
-
332
-    getEventStartDate(event: Object) {
333
-        return event.date_begin.split(" ")[0];
334
-    }
335
-
336
-    getEventStartTime(event: Object) {
337
-        if (event !== undefined && Object.keys(event).length > 0 && event.date_begin !== null)
338
-            return this.formatTime(event.date_begin.split(" ")[1]);
339
-        else
340
-            return "";
341
-    }
342
-
343
-    getEventEndTime(event: Object) {
344
-        if (event !== undefined && Object.keys(event).length > 0 && event.date_end !== null)
345
-            return this.formatTime(event.date_end.split(" ")[1]);
346
-        else
347
-            return "";
348
-    }
349
-
350
-    getFormattedTime(event: Object) {
351
-        if (this.getEventEndTime(event) !== "")
352
-            return this.getEventStartTime(event) + " - " + this.getEventEndTime(event);
353
-        else
354
-            return this.getEventStartTime(event);
355
-    }
356
-
357
-    formatTime(time: string) {
358
-        let array = time.split(':');
359
-        return array[0] + ':' + array[1];
360
-    }
361
-
362
-    onModalClosed() {
363
-        this.setState({
364
-            modalCurrentDisplayItem: {},
365
-        });
366
-    }
367
-
368 255
     render() {
369 256
         const nav = this.props.navigation;
370 257
         return (
371 258
             <BaseContainer navigation={nav} headerTitle={i18n.t('screens.planning')}>
372
-                <Modalize ref={this.modalRef}
373
-                          modalStyle={{
374
-                              backgroundColor: ThemeManager.getCurrentThemeVariables().containerBgColor,
375
-                          }}
376
-                    // adjustToContentHeight // Breaks when displaying full screen, half, then full again
377
-                          HeaderComponent={() => this.getModalHeader()}
378
-                          onClosed={() => this.onModalClosed()}>
379
-                    {this.getModalContent()}
380
-                </Modalize>
381 259
                 <Agenda
382 260
                     // the list of items that have to be displayed in agenda. If you want to render item as empty date
383 261
                     // the value of date key kas to be an empty array []. If there exists no value for date key it is
@@ -431,14 +309,6 @@ export default class PlanningScreen extends React.Component<Props, State> {
431 309
                         agendaDayNumColor: ThemeManager.getCurrentThemeVariables().listNoteColor,
432 310
                         agendaTodayColor: ThemeManager.getCurrentThemeVariables().brandPrimary,
433 311
                         agendaKnobColor: ThemeManager.getCurrentThemeVariables().brandPrimary,
434
-                        // Fix for days hiding behind knob
435
-                        'stylesheet.calendar.header': {
436
-                            week: {
437
-                                marginTop: 0,
438
-                                flexDirection: 'row',
439
-                                justifyContent: 'space-between'
440
-                            }
441
-                        }
442 312
                     }}
443 313
                 />
444 314
             </BaseContainer>

+ 1
- 0
translations/en.json View File

@@ -2,6 +2,7 @@
2 2
   "screens": {
3 3
     "home": "Home",
4 4
     "planning": "Planning",
5
+    "planningDisplayScreen": "Event Details",
5 6
     "proxiwash": "Proxiwash",
6 7
     "proximo": "Proximo",
7 8
     "menuSelf": "RU Menu",

+ 1
- 0
translations/fr.json View File

@@ -2,6 +2,7 @@
2 2
   "screens": {
3 3
     "home": "Accueil",
4 4
     "planning": "Planning",
5
+    "planningDisplayScreen": "Détails",
5 6
     "proxiwash": "Proxiwash",
6 7
     "proximo": "Proximo",
7 8
     "menuSelf": "Menu du RU",

+ 42
- 0
utils/PlanningEventManager.js View File

@@ -0,0 +1,42 @@
1
+
2
+export default class PlanningEventManager {
3
+    static isEventBefore(event1: Object, event2: Object) {
4
+        let date1 = new Date();
5
+        let date2 = new Date();
6
+        let timeArray = this.getEventStartTime(event1).split(":");
7
+        date1.setHours(parseInt(timeArray[0]), parseInt(timeArray[1]));
8
+        timeArray = this.getEventStartTime(event2).split(":");
9
+        date2.setHours(parseInt(timeArray[0]), parseInt(timeArray[1]));
10
+        return date1 < date2;
11
+    }
12
+
13
+    static getEventStartDate(event: Object) {
14
+        return event.date_begin.split(" ")[0];
15
+    }
16
+
17
+    static getEventStartTime(event: Object) {
18
+        if (event !== undefined && Object.keys(event).length > 0 && event.date_begin !== null)
19
+            return this.formatTime(event.date_begin.split(" ")[1]);
20
+        else
21
+            return "";
22
+    }
23
+
24
+    static getEventEndTime(event: Object) {
25
+        if (event !== undefined && Object.keys(event).length > 0 && event.date_end !== null)
26
+            return this.formatTime(event.date_end.split(" ")[1]);
27
+        else
28
+            return "";
29
+    }
30
+
31
+    static getFormattedTime(event: Object) {
32
+        if (this.getEventEndTime(event) !== "")
33
+            return this.getEventStartTime(event) + " - " + this.getEventEndTime(event);
34
+        else
35
+            return this.getEventStartTime(event);
36
+    }
37
+
38
+    static formatTime(time: string) {
39
+        let array = time.split(':');
40
+        return array[0] + ':' + array[1];
41
+    }
42
+}

Loading…
Cancel
Save