Improved url handling

This commit is contained in:
Arnaud Vergnet 2020-04-08 12:10:06 +02:00
parent 41b9194d98
commit 6a6049220d
7 changed files with 121 additions and 79 deletions

70
App.js
View file

@ -5,7 +5,7 @@ import {Platform, StatusBar} from 'react-native';
import LocaleManager from './src/managers/LocaleManager';
import AsyncStorageManager from "./src/managers/AsyncStorageManager";
import CustomIntroSlider from "./src/components/Custom/CustomIntroSlider";
import {Linking, SplashScreen} from 'expo';
import {SplashScreen} from 'expo';
import ThemeManager from './src/managers/ThemeManager';
import {NavigationContainer} from '@react-navigation/native';
import {createStackNavigator} from '@react-navigation/stack';
@ -15,6 +15,7 @@ import {Provider as PaperProvider} from 'react-native-paper';
import AprilFoolsManager from "./src/managers/AprilFoolsManager";
import Update from "./src/constants/Update";
import ConnectionManager from "./src/managers/ConnectionManager";
import URLHandler from "./src/utils/URLHandler";
type Props = {};
@ -43,11 +44,13 @@ export default class App extends React.Component<Props, State> {
navigatorRef: Object;
defaultRoute: Array<string>;
defaultRoute: string | null;
defaultData: Object;
createDrawerNavigator: Function;
urlHandler: URLHandler;
constructor() {
super();
LocaleManager.initTranslations();
@ -55,61 +58,25 @@ export default class App extends React.Component<Props, State> {
this.onUpdateTheme = this.onUpdateTheme.bind(this);
SplashScreen.preventAutoHide();
this.navigatorRef = React.createRef();
this.defaultRoute = [];
this.defaultRoute = null;
this.defaultData = {};
// this.defaultRoute = ["main", "home", "club-information"];
// this.defaultData = {clubId: 0};
this.handleUrls();
this.urlHandler = new URLHandler(this.onInitialURLParsed, this.onDetectURL);
this.urlHandler.listen();
}
handleUrls() {
console.log(Linking.makeUrl('main/home/club-information', {clubId: 1}));
Linking.addEventListener('url', this.onUrl);
Linking.parseInitialURLAsync().then(this.onParsedUrl);
}
onUrl = (url: string) => {
this.onParsedUrl(Linking.parse(url));
onInitialURLParsed = ({route, data}: Object) => {
this.defaultRoute = route;
this.defaultData = data;
};
onParsedUrl = ({path, queryParams}: Object) => {
if (path !== null) {
let pathArray = path.split('/');
if (this.isClubInformationLink(pathArray))
this.handleClubInformationUrl(queryParams);
else if (this.isPlanningInformationLink(pathArray))
this.handlePlanningInformationUrl(queryParams);
}
onDetectURL = ({route, data}: Object) => {
// Navigate to nested navigator and pass data to the index screen
this.navigatorRef.current.navigate('home', {
screen: 'index',
params: {nextScreen: route, data: data, shouldOpen: true}
});
};
isClubInformationLink(pathArray: Array<string>) {
return pathArray[0] === "main" && pathArray[1] === "home" && pathArray[2] === "club-information";
}
isPlanningInformationLink(pathArray: Array<string>) {
return pathArray[0] === "main" && pathArray[1] === "home" && pathArray[2] === "planning-information";
}
handleClubInformationUrl(params: Object) {
if (params !== undefined && params.clubId !== undefined) {
let id = parseInt(params.clubId);
if (!isNaN(id)) {
this.defaultRoute = ["main", "home", "club-information"];
this.defaultData = {clubId: id};
}
}
}
handlePlanningInformationUrl(params: Object) {
if (params !== undefined && params.eventId !== undefined) {
let id = parseInt(params.eventId);
if (!isNaN(id)) {
this.defaultRoute = ["main", "home", "planning-information"];
this.defaultData = {eventId: id};
}
}
}
/**
* Updates the theme
*/
@ -156,7 +123,8 @@ export default class App extends React.Component<Props, State> {
} catch (e) {
}
this.createDrawerNavigator = () => <DrawerNavigator defaultPath={this.defaultRoute} defaultData={this.defaultData}/>;
this.createDrawerNavigator = () => <DrawerNavigator defaultRoute={this.defaultRoute}
defaultData={this.defaultData}/>;
this.onLoadFinished();
}

View file

@ -196,7 +196,7 @@ export default class ConnectionManager {
let data = {};
if (keys !== null && values !== null && keys.length === values.length)
data = this.generatePostArguments(keys, values);
console.log(data);
// console.log(data);
fetch(API_ENDPOINT + path, {
method: 'POST',
headers: new Headers({
@ -209,7 +209,7 @@ export default class ConnectionManager {
})
}).then(async (response) => response.json())
.then((response: response_format) => {
console.log(response);
// console.log(response);
if (this.isResponseValid(response)) {
if (response.error === ERROR_TYPE.SUCCESS)
resolve(response.data);

View file

@ -317,35 +317,25 @@ function getDrawerContent(props) {
}
type Props = {
defaultPath: Array<string>,
defaultRoute: string | null,
defaultData: Object
}
export default class DrawerNavigator extends React.Component<Props> {
defaultRoute: string;
defaultSubRoute: string | null;
createTabNavigator: Object;
constructor(props: Object) {
super(props);
this.defaultRoute = 'Main';
this.defaultSubRoute = null;
if (props.defaultPath.length > 0)
this.defaultRoute = props.defaultPath[0];
if (props.defaultPath.length > 1)
this.defaultSubRoute = props.defaultPath[1];
this.createTabNavigator = () => <TabNavigator defaultPath={props.defaultPath} defaultData={props.defaultData}/>
this.createTabNavigator = () => <TabNavigator defaultRoute={props.defaultRoute} defaultData={props.defaultData}/>
}
render() {
return (
<Drawer.Navigator
initialRouteName={this.defaultRoute}
initialRouteName={'Main'}
headerMode={'float'}
backBehavior={'initialRoute'}
drawerType={'front'}

View file

@ -145,6 +145,10 @@ function PlanningStackComponent() {
const HomeStack = createStackNavigator();
function HomeStackComponent(initialRoute: string | null, defaultData: Object) {
let data;
if (initialRoute !== null)
data = {data: defaultData, nextScreen: initialRoute, shouldOpen: true};
return (
<HomeStack.Navigator
initialRouteName={"index"}
@ -161,7 +165,7 @@ function HomeStackComponent(initialRoute: string | null, defaultData: Object) {
headerLeft: openDrawer
};
}}
initialParams={{data: defaultData, nextScreen: initialRoute}}
initialParams={data}
/>
<HomeStack.Screen
name="planning-information"
@ -212,7 +216,7 @@ function PlanexStackComponent() {
const Tab = createMaterialBottomTabNavigator();
type Props = {
defaultPath: Array<string>,
defaultRoute: string | null,
defaultData: Object
}
@ -221,19 +225,17 @@ class TabNavigator extends React.Component<Props>{
createHomeStackComponent: Object;
colors: Object;
defaultRoute: string;
constructor(props) {
super(props);
this.colors = props.theme.colors;
this.defaultRoute = AsyncStorageManager.getInstance().preferences.defaultStartScreen.current.toLowerCase();
this.defaultSubRoute = null;
if (props.defaultPath.length > 1)
this.defaultRoute = props.defaultPath[1];
if (props.defaultPath.length > 2)
this.defaultSubRoute = props.defaultPath[2];
if (props.defaultRoute !== null)
this.defaultRoute = 'home';
this.createHomeStackComponent = () => HomeStackComponent(this.defaultSubRoute, props.defaultData);
this.createHomeStackComponent = () => HomeStackComponent(props.defaultRoute, props.defaultData);
}
render() {

View file

@ -61,6 +61,7 @@ class ClubDisplayScreen extends React.Component<Props, State> {
super(props);
this.colors = props.theme.colors;
console.log(this.props.route.params);
if (this.props.route.params.data !== undefined && this.props.route.params.categories !== undefined) {
this.displayData = this.props.route.params.data;
this.categories = this.props.route.params.categories;

View file

@ -14,6 +14,7 @@ import {openBrowser} from "../utils/WebBrowser";
import ActionsDashBoardItem from "../components/Home/ActionsDashboardItem";
import HeaderButton from "../components/Custom/HeaderButton";
import ConnectionManager from "../managers/ConnectionManager";
import {CommonActions} from '@react-navigation/native';
// import DATA from "../dashboard_data.json";
@ -52,9 +53,6 @@ class HomeScreen extends React.Component<Props> {
this.colors = props.theme.colors;
this.isLoggedIn = null;
if (this.props.route.params.nextScreen !== undefined && this.props.route.params.nextScreen !== null) {
this.props.navigation.navigate(this.props.route.params.nextScreen, this.props.route.params.data);
}
}
/**
@ -79,7 +77,14 @@ class HomeScreen extends React.Component<Props> {
headerRight: this.getHeaderButton,
});
}
// TODO if already on home screen
if (this.props.route.params !== undefined) {
if (this.props.route.params.shouldOpen !== undefined && this.props.route.params.shouldOpen) {
this.props.navigation.navigate(this.props.route.params.nextScreen, this.props.route.params.data);
// reset params to prevent infinite loop
this.props.navigation.dispatch(CommonActions.setParams({ shouldOpen: false }));
}
}
};
getHeaderButton = () => {

76
src/utils/URLHandler.js Normal file
View file

@ -0,0 +1,76 @@
// @flow
import {Linking} from 'expo';
export default class URLHandler {
static CLUB_INFO_ROUTE = "club-information";
static EVENT_INFO_ROUTE = "planning-information";
onInitialURLParsed: Function;
onDetectURL: Function;
constructor(onInitialURLParsed: Function, onDetectURL: Function) {
this.onInitialURLParsed = onInitialURLParsed;
this.onDetectURL = onDetectURL;
}
listen() {
console.log(Linking.makeUrl('main/home/club-information', {clubId: 1}));
Linking.addEventListener('url', this.onUrl);
Linking.parseInitialURLAsync().then(this.onInitialUrl);
}
onUrl = ({url}: Object) => {
let data = this.getUrlData(Linking.parse(url));
if (data !== null)
this.onDetectURL(data);
};
onInitialUrl = ({path, queryParams}: Object) => {
let data = this.getUrlData({path, queryParams});
if (data !== null)
this.onInitialURLParsed(data);
};
getUrlData({path, queryParams}: Object) {
let data = null;
if (path !== null) {
let pathArray = path.split('/');
if (this.isClubInformationLink(pathArray))
data = this.generateClubInformationData(queryParams);
else if (this.isPlanningInformationLink(pathArray))
data = this.generatePlanningInformationData(queryParams);
}
return data;
}
isClubInformationLink(pathArray: Array<string>) {
return pathArray[0] === "main" && pathArray[1] === "home" && pathArray[2] === "club-information";
}
isPlanningInformationLink(pathArray: Array<string>) {
return pathArray[0] === "main" && pathArray[1] === "home" && pathArray[2] === "planning-information";
}
generateClubInformationData(params: Object): Object | null {
if (params !== undefined && params.clubId !== undefined) {
let id = parseInt(params.clubId);
if (!isNaN(id)) {
return {route: URLHandler.CLUB_INFO_ROUTE, data: {clubId: id}};
}
}
return null;
}
generatePlanningInformationData(params: Object): Object | null {
if (params !== undefined && params.eventId !== undefined) {
let id = parseInt(params.eventId);
if (!isNaN(id)) {
return {route: URLHandler.EVENT_INFO_ROUTE, data: {eventId: id}};
}
}
return null;
}
}