Updated react navigation to v5

This commit is contained in:
keplyx 2020-03-05 10:29:15 +01:00
parent 7acbb88641
commit 7e48300fa0
6 changed files with 326 additions and 263 deletions

54
App.js
View file

@ -3,15 +3,17 @@
import * as React from 'react';
import {Platform, StatusBar} from 'react-native';
import {Root, StyleProvider} from 'native-base';
import {createAppContainerWithInitialRoute} from './navigation/AppNavigator';
import LocaleManager from './utils/LocaleManager';
import * as Font from 'expo-font';
import {clearThemeCache} from 'native-base-shoutem-theme';
import AsyncStorageManager from "./utils/AsyncStorageManager";
import CustomIntroSlider from "./components/CustomIntroSlider";
import {AppLoading} from 'expo';
import {SplashScreen} from 'expo';
import NotificationsManager from "./utils/NotificationsManager";
import ThemeManager from './utils/ThemeManager';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import DrawerNavigator from './navigation/DrawerNavigator';
type Props = {};
@ -22,6 +24,8 @@ type State = {
currentTheme: ?Object,
};
const Stack = createStackNavigator();
export default class App extends React.Component<Props, State> {
state = {
@ -31,16 +35,9 @@ export default class App extends React.Component<Props, State> {
currentTheme: null,
};
onIntroDone: Function;
loadAssetsAsync: Function;
onLoadFinished: Function;
constructor(props: Object) {
super(props);
LocaleManager.initTranslations();
this.onIntroDone = this.onIntroDone.bind(this);
this.loadAssetsAsync = this.loadAssetsAsync.bind(this);
this.onLoadFinished = this.onLoadFinished.bind(this);
}
/**
@ -76,19 +73,29 @@ export default class App extends React.Component<Props, State> {
AsyncStorageManager.getInstance().savePref(AsyncStorageManager.getInstance().preferences.showUpdate5.key, '0');
}
async componentDidMount() {
await this.loadAssetsAsync();
}
async loadAssetsAsync() {
// Wait for custom fonts to be loaded before showing the app
console.log("loading Fonts");
SplashScreen.preventAutoHide();
await Font.loadAsync({
'Roboto': require('native-base/Fonts/Roboto.ttf'),
'Roboto_medium': require('native-base/Fonts/Roboto_medium.ttf'),
'material-community': require('native-base/Fonts/MaterialCommunityIcons.ttf'),
});
console.log("loading preferences");
await AsyncStorageManager.getInstance().loadPreferences();
ThemeManager.getInstance().setUpdateThemeCallback(() => this.updateTheme());
console.log("loading Expo token");
await NotificationsManager.initExpoToken();
console.log("loaded");
this.onLoadFinished();
}
onLoadFinished() {
console.log("finished");
// Only show intro if this is the first time starting the app
this.setState({
isLoading: false,
@ -97,33 +104,30 @@ export default class App extends React.Component<Props, State> {
showUpdate: AsyncStorageManager.getInstance().preferences.showUpdate5.current === '1'
});
// Status bar goes dark if set too fast
setTimeout(this.setupStatusBar,
1000
)
setTimeout(this.setupStatusBar, 1000);
SplashScreen.hide();
}
/**
* Renders the app based on loading state
*/
render() {
console.log("render");
if (this.state.isLoading) {
return (
<AppLoading
startAsync={this.loadAssetsAsync}
onFinish={this.onLoadFinished}
onError={console.warn}
/>
);
}
if (this.state.showIntro || this.state.showUpdate) {
return null;
} else if (this.state.showIntro || this.state.showUpdate) {
return <CustomIntroSlider onDone={this.onIntroDone}
isUpdate={this.state.showUpdate && !this.state.showIntro}/>;
} else {
const AppNavigator = createAppContainerWithInitialRoute(AsyncStorageManager.getInstance().preferences.defaultStartScreen.current);
return (
<Root>
<StyleProvider style={this.state.currentTheme}>
<AppNavigator/>
<NavigationContainer>
<Stack.Navigator headerMode="none">
<Stack.Screen name="Root" component={DrawerNavigator} />
</Stack.Navigator>
</NavigationContainer>
</StyleProvider>
</Root>
);

View file

@ -4,11 +4,9 @@ import * as React from 'react';
import {Container} from "native-base";
import CustomHeader from "./CustomHeader";
import CustomMaterialIcon from "./CustomMaterialIcon";
import {Platform, StatusBar, View} from "react-native";
import {Platform, View} from "react-native";
import ThemeManager from "../utils/ThemeManager";
import Touchable from "react-native-platform-touchable";
import {ScreenOrientation} from "expo";
import {NavigationActions} from "react-navigation";
type Props = {
@ -39,81 +37,22 @@ export default class BaseContainer extends React.Component<Props, State> {
hideHeaderOnLandscape: false,
headerSubtitle: '',
};
willBlurSubscription: function;
willFocusSubscription: function;
state = {
isHeaderVisible: true,
};
onDrawerPress: Function;
onWillFocus: Function;
onWillBlur: Function;
onChangeOrientation: Function;
constructor() {
super();
this.onDrawerPress = this.onDrawerPress.bind(this);
this.onWillFocus = this.onWillFocus.bind(this);
this.onWillBlur = this.onWillBlur.bind(this);
this.onChangeOrientation = this.onChangeOrientation.bind(this);
}
onDrawerPress() {
this.props.navigation.toggleDrawer();
}
onWillFocus() {
if (this.props.enableRotation) {
ScreenOrientation.unlockAsync();
ScreenOrientation.addOrientationChangeListener(this.onChangeOrientation);
}
}
onWillBlur() {
if (this.props.enableRotation)
ScreenOrientation.lockAsync(ScreenOrientation.Orientation.PORTRAIT);
}
onChangeOrientation(OrientationChangeEvent) {
if (this.props.hideHeaderOnLandscape) {
let isLandscape = OrientationChangeEvent.orientationInfo.orientation === ScreenOrientation.Orientation.LANDSCAPE ||
OrientationChangeEvent.orientationInfo.orientation === ScreenOrientation.Orientation.LANDSCAPE_LEFT ||
OrientationChangeEvent.orientationInfo.orientation === ScreenOrientation.Orientation.LANDSCAPE_RIGHT;
this.setState({isHeaderVisible: !isLandscape});
const setParamsAction = NavigationActions.setParams({
params: {showTabBar: !isLandscape},
key: this.props.navigation.state.key,
});
this.props.navigation.dispatch(setParamsAction);
StatusBar.setHidden(isLandscape);
}
}
/**
* Register for blur event to close side menu on screen change
*/
componentDidMount() {
this.willFocusSubscription = this.props.navigation.addListener(
'willFocus',
this.onWillFocus
);
this.willBlurSubscription = this.props.navigation.addListener(
'willBlur',
this.onWillBlur
);
}
/**
* Unregister from event when un-mounting components
*/
componentWillUnmount() {
if (this.willBlurSubscription !== undefined)
this.willBlurSubscription.remove();
if (this.willFocusSubscription !== undefined)
this.willFocusSubscription.remove();
}
render() {
// console.log("rendering BaseContainer");
return (

View file

@ -1,14 +0,0 @@
// @flow
import {createAppContainer} from 'react-navigation';
import {createDrawerNavigatorWithInitialRoute} from './DrawerNavigator';
/**
* Create a stack navigator using the drawer to handle navigation between screens
*/
function createAppContainerWithInitialRoute(initialRoute: string) {
return createAppContainer(createDrawerNavigatorWithInitialRoute(initialRoute));
}
export {createAppContainerWithInitialRoute};

View file

@ -1,7 +1,8 @@
// @flow
import { createDrawerNavigator } from 'react-navigation-drawer';
import {createMaterialBottomTabNavigatorWithInitialRoute} from './MainTabNavigator';
import * as React from 'react';
import {createDrawerNavigator} from '@react-navigation/drawer';
import TabNavigator from './MainTabNavigator';
import SettingsScreen from '../screens/SettingsScreen';
import AboutScreen from '../screens/About/AboutScreen';
import AboutDependenciesScreen from '../screens/About/AboutDependenciesScreen';
@ -15,65 +16,145 @@ import EntScreen from "../screens/Websites/EntScreen";
import AvailableRoomScreen from "../screens/Websites/AvailableRoomScreen";
import DebugScreen from '../screens/DebugScreen';
import Sidebar from "../components/Sidebar";
import {createStackNavigator, TransitionPresets} from "react-navigation-stack";
import {createStackNavigator, TransitionPresets} from "@react-navigation/stack";
const AboutStack = createStackNavigator({
AboutScreen: {screen: AboutScreen},
AboutDependenciesScreen: {screen: AboutDependenciesScreen},
DebugScreen: {screen: DebugScreen},
},
{
initialRouteName: "AboutScreen",
mode: 'card',
headerMode: "none",
defaultNavigationOptions: {
gestureEnabled: true,
cardOverlayEnabled: true,
...TransitionPresets.SlideFromRightIOS,
},
});
const AboutStack = createStackNavigator();
// Create a stack to use animations
function createDrawerStackWithInitialRoute(initialRoute: string) {
return createStackNavigator({
Main: createMaterialBottomTabNavigatorWithInitialRoute(initialRoute),
SettingsScreen: {screen: SettingsScreen},
AboutScreen: AboutStack,
SelfMenuScreen: {screen: SelfMenuScreen},
TutorInsaScreen: {screen: TutorInsaScreen},
AmicaleScreen: {screen: AmicaleScreen},
WiketudScreen: {screen: WiketudScreen},
ElusEtudScreen: {screen: ElusEtudScreen},
BlueMindScreen: {screen: BlueMindScreen},
EntScreen: {screen: EntScreen},
AvailableRoomScreen: {screen: AvailableRoomScreen},
},
{
initialRouteName: "Main",
mode: 'card',
headerMode: "none",
defaultNavigationOptions: {
function AboutStackComponent() {
return (
<AboutStack.Navigator
initialRouteName="AboutScreen"
mode='card'
headerMode="none"
screenOptions={{
gestureEnabled: true,
cardOverlayEnabled: true,
...TransitionPresets.SlideFromRightIOS,
},
});
}}
>
<AboutStack.Screen
name="AboutScreen"
component={AboutScreen}
/>
<AboutStack.Screen
name="AboutDependenciesScreen"
component={AboutDependenciesScreen}
/>
<AboutStack.Screen
name="DebugScreen"
component={DebugScreen}
/>
</AboutStack.Navigator>
);
}
/**
* Creates the drawer navigation stack
*/
function createDrawerNavigatorWithInitialRoute(initialRoute: string) {
return createDrawerNavigator({
Main: createDrawerStackWithInitialRoute(initialRoute),
}, {
contentComponent: Sidebar,
initialRouteName: 'Main',
backBehavior: 'initialRoute',
drawerType: 'front',
useNativeAnimations: true,
});
const Drawer = createDrawerNavigator();
function getDrawerContent(nav) {
return <Sidebar navigation={nav}/>
}
export {createDrawerNavigatorWithInitialRoute};
export default function DrawerNavigator() {
return (
<Drawer.Navigator
initialRouteName={'Main'}
mode='card'
drawerContent={props => getDrawerContent(props.navigation)}
screenOptions={{
gestureEnabled: true,
cardOverlayEnabled: true,
...TransitionPresets.SlideFromRightIOS,
}}
>
<Drawer.Screen
name="Main"
component={TabNavigator}
>
</Drawer.Screen>
<Drawer.Screen
name="SettingsScreen"
component={SettingsScreen}
/>
<Drawer.Screen
name="AboutScreen"
component={AboutStackComponent}
/>
<Drawer.Screen
name="SelfMenuScreen"
component={SelfMenuScreen}
/>
<Drawer.Screen
name="TutorInsaScreen"
component={TutorInsaScreen}
/>
<Drawer.Screen
name="AmicaleScreen"
component={AmicaleScreen}
/>
<Drawer.Screen
name="WiketudScreen"
component={WiketudScreen}
/>
<Drawer.Screen
name="ElusEtudScreen"
component={ElusEtudScreen}
/>
<Drawer.Screen
name="BlueMindScreen"
component={BlueMindScreen}
/>
<Drawer.Screen
name="EntScreen"
component={EntScreen}
/>
<Drawer.Screen
name="AvailableRoomScreen"
component={AvailableRoomScreen}
/>
</Drawer.Navigator>
);
}
//
// // Create a stack to use animations
// function createDrawerStackWithInitialRoute(initialRoute: string) {
// return createStackNavigator({
// Main: createMaterialBottomTabNavigatorWithInitialRoute(initialRoute),
// SettingsScreen: {screen: SettingsScreen},
// AboutScreen: AboutStack,
// SelfMenuScreen: {screen: SelfMenuScreen},
// TutorInsaScreen: {screen: TutorInsaScreen},
// AmicaleScreen: {screen: AmicaleScreen},
// WiketudScreen: {screen: WiketudScreen},
// ElusEtudScreen: {screen: ElusEtudScreen},
// BlueMindScreen: {screen: BlueMindScreen},
// EntScreen: {screen: EntScreen},
// AvailableRoomScreen: {screen: AvailableRoomScreen},
// },
// {
// initialRouteName: "Main",
// mode: 'card',
// headerMode: "none",
// defaultNavigationOptions: {
// gestureEnabled: true,
// cardOverlayEnabled: true,
// ...TransitionPresets.SlideFromRightIOS,
// },
// });
// }
// /**
// * Creates the drawer navigation stack
// */
// function createDrawerNavigatorWithInitialRoute(initialRoute: string) {
// return createDrawerNavigator({
// Main: createDrawerStackWithInitialRoute(initialRoute),
// }, {
// contentComponent: Sidebar,
// initialRouteName: 'Main',
// backBehavior: 'initialRoute',
// drawerType: 'front',
// useNativeAnimations: true,
// });
// }
//
// export {createDrawerNavigatorWithInitialRoute};

View file

@ -1,6 +1,6 @@
import * as React from 'react';
import {createStackNavigator, TransitionPresets} from 'react-navigation-stack';
import {createMaterialBottomTabNavigator} from "react-navigation-material-bottom-tabs";
import {createStackNavigator, TransitionPresets} from '@react-navigation/stack';
import {createMaterialBottomTabNavigator} from "@react-navigation/material-bottom-tabs";
import HomeScreen from '../screens/HomeScreen';
import PlanningScreen from '../screens/PlanningScreen';
@ -13,6 +13,11 @@ import ProximoAboutScreen from "../screens/Proximo/ProximoAboutScreen";
import PlanexScreen from '../screens/Websites/PlanexScreen';
import CustomMaterialIcon from "../components/CustomMaterialIcon";
import ThemeManager from "../utils/ThemeManager";
import AboutScreen from "../screens/About/AboutScreen";
import AboutDependenciesScreen from "../screens/About/AboutDependenciesScreen";
import DebugScreen from "../screens/DebugScreen";
import SettingsScreen from "../screens/SettingsScreen";
import AsyncStorageManager from "../utils/AsyncStorageManager";
const TAB_ICONS = {
Home: 'triangle',
@ -22,106 +27,153 @@ const TAB_ICONS = {
Planex: 'timetable',
};
const ProximoStack = createStackNavigator({
ProximoMainScreen: {screen: ProximoMainScreen},
ProximoListScreen: {screen: ProximoListScreen},
ProximoAboutScreen: {
screen: ProximoAboutScreen,
navigationOptions: () => ({
...TransitionPresets.ModalSlideFromBottomIOS,
}),
},
},
{
initialRouteName: "ProximoMainScreen",
mode: 'card',
headerMode: "none",
defaultNavigationOptions: {
gestureEnabled: true,
cardOverlayEnabled: true,
...TransitionPresets.SlideFromRightIOS,
},
});
const ProximoStack = createStackNavigator();
const ProxiwashStack = createStackNavigator({
ProxiwashScreen: {screen: ProxiwashScreen},
ProxiwashAboutScreen: {screen: ProxiwashAboutScreen},
},
{
initialRouteName: "ProxiwashScreen",
mode: 'card',
headerMode: "none",
defaultNavigationOptions: {
gestureEnabled: true,
cardOverlayEnabled: true,
...TransitionPresets.ModalSlideFromBottomIOS,
},
});
const PlanningStack = createStackNavigator({
PlanningScreen: {screen: PlanningScreen},
PlanningDisplayScreen: {screen: PlanningDisplayScreen},
},
{
initialRouteName: "PlanningScreen",
mode: 'card',
headerMode: "none",
defaultNavigationOptions: {
gestureEnabled: true,
cardOverlayEnabled: true,
...TransitionPresets.ModalSlideFromBottomIOS,
},
});
const HomeStack = createStackNavigator({
HomeScreen: {screen: HomeScreen},
PlanningDisplayScreen: {screen: PlanningDisplayScreen},
},
{
initialRouteName: "HomeScreen",
mode: 'card',
headerMode: "none",
defaultNavigationOptions: {
gestureEnabled: true,
cardOverlayEnabled: true,
...TransitionPresets.ModalSlideFromBottomIOS,
},
});
function createMaterialBottomTabNavigatorWithInitialRoute(initialRoute: string) {
return createMaterialBottomTabNavigator({
Home: HomeStack,
Planning: PlanningStack,
Proxiwash: ProxiwashStack,
Proximo: ProximoStack,
Planex: {
screen: PlanexScreen,
navigationOptions: ({navigation}) => {
const showTabBar = navigation.state && navigation.state.params ? navigation.state.params.showTabBar : true;
return {
tabBarVisible: showTabBar,
};
},
},
}, {
defaultNavigationOptions: ({navigation}) => ({
tabBarIcon: ({focused, tintColor}) => {
let icon = TAB_ICONS[navigation.state.routeName];
// tintColor is ignoring activeColor et inactiveColor for some reason
let color = focused ? "#f0edf6" : "#4e1108";
return <CustomMaterialIcon icon={icon} color={color}/>;
},
tabBarVisible: true,
}),
order: ['Proximo', 'Planning', 'Home', 'Proxiwash', 'Planex'],
initialRouteName: initialRoute,
activeColor: '#f0edf6',
inactiveColor: '#4e1108',
backBehavior: 'initialRoute',
barStyle: {backgroundColor: ThemeManager.getCurrentThemeVariables().brandPrimary},
});
function ProximoStackComponent() {
return (
<ProximoStack.Navigator
initialRouteName="ProximoMainScreen"
mode='card'
headerMode="none"
screenOptions={{
gestureEnabled: true,
cardOverlayEnabled: true,
...TransitionPresets.SlideFromRightIOS,
}}
>
<ProximoStack.Screen
name="ProximoMainScreen"
component={ProximoMainScreen}
/>
<ProximoStack.Screen
name="ProximoListScreen"
component={ProximoListScreen}
/>
<ProximoStack.Screen
name="ProximoAboutScreen"
component={ProximoAboutScreen}
options={{
...TransitionPresets.ModalSlideFromBottomIOS,
}}
/>
</ProximoStack.Navigator>
);
}
const ProxiwashStack = createStackNavigator();
export {createMaterialBottomTabNavigatorWithInitialRoute};
function ProxiwashStackComponent() {
return (
<ProxiwashStack.Navigator
initialRouteName="ProxiwashScreen"
mode='card'
headerMode="none"
screenOptions={{
gestureEnabled: true,
cardOverlayEnabled: true,
...TransitionPresets.ModalSlideFromBottomIOS,
}}
>
<ProxiwashStack.Screen
name="ProxiwashScreen"
component={ProxiwashScreen}
/>
<ProxiwashStack.Screen
name="ProxiwashAboutScreen"
component={ProxiwashAboutScreen}
/>
</ProxiwashStack.Navigator>
);
}
const PlanningStack = createStackNavigator();
function PlanningStackComponent() {
return (
<PlanningStack.Navigator
initialRouteName="PlanningScreen"
mode='card'
headerMode="none"
screenOptions={{
gestureEnabled: true,
cardOverlayEnabled: true,
...TransitionPresets.ModalSlideFromBottomIOS,
}}
>
<PlanningStack.Screen
name="PlanningScreen"
component={PlanningScreen}
/>
<PlanningStack.Screen
name="PlanningDisplayScreen"
component={PlanningDisplayScreen}
/>
</PlanningStack.Navigator>
);
}
const HomeStack = createStackNavigator();
function HomeStackComponent() {
return (
<HomeStack.Navigator
initialRouteName="HomeScreen"
mode='card'
headerMode="none"
screenOptions={{
gestureEnabled: true,
cardOverlayEnabled: true,
...TransitionPresets.ModalSlideFromBottomIOS,
}}
>
<HomeStack.Screen
name="HomeScreen"
component={HomeScreen}
/>
<HomeStack.Screen
name="PlanningDisplayScreen"
component={PlanningDisplayScreen}
/>
</HomeStack.Navigator>
);
}
const Tab = createMaterialBottomTabNavigator();
export default function TabNavigator() {
return (
<Tab.Navigator
initialRouteName={AsyncStorageManager.getInstance().preferences.defaultStartScreen}
barStyle={{backgroundColor: ThemeManager.getCurrentThemeVariables().brandPrimary}}
screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
let icon = TAB_ICONS[route.name];
// tintColor is ignoring activeColor and inactiveColor for some reason
color = focused ? "#f0edf6" : "#4e1108";
return <CustomMaterialIcon icon={icon} color={color}/>;
},
})}
>
<Tab.Screen
name="Proximo"
component={ProximoStackComponent}
/>
<Tab.Screen
name="Planning"
component={PlanningStackComponent}
/>
<Tab.Screen
name="Home"
component={HomeStackComponent}
/>
<Tab.Screen
name="Proxiwash"
component={ProxiwashStackComponent}
/>
<Tab.Screen
name="Planex"
component={PlanexScreen}
/>
</Tab.Navigator>
);
}

View file

@ -9,11 +9,17 @@
},
"dependencies": {
"@react-native-community/masked-view": "0.1.5",
"@react-navigation/bottom-tabs": "^5.1.1",
"@react-navigation/drawer": "^5.1.1",
"@react-navigation/material-bottom-tabs": "^5.1.1",
"@react-navigation/native": "^5.0.9",
"@react-navigation/stack": "^5.1.1",
"expo": "^36.0.0",
"expo-font": "~8.0.0",
"expo-linear-gradient": "~8.0.0",
"expo-localization": "~8.0.0",
"expo-permissions": "~8.0.0",
"expo-web-browser": "~8.0.0",
"i18n-js": "^3.3.0",
"native-base": "^2.12.1",
"native-base-shoutem-theme": "^0.3.1",
@ -33,12 +39,7 @@
"react-native-safe-area-context": "0.6.0",
"react-native-screens": "2.0.0-alpha.12",
"react-native-status-bar-height": "^2.3.1",
"react-native-webview": "7.4.3",
"react-navigation": "^4.1.0",
"react-navigation-drawer": "^2.3.3",
"react-navigation-material-bottom-tabs": "^2.1.5",
"react-navigation-stack": "^2.1.0",
"react-navigation-transitions": "^1.0.12"
"react-native-webview": "7.4.3"
},
"devDependencies": {
"babel-preset-expo": "^8.0.0"