Browse Source

Improved url handling

Arnaud Vergnet 1 year ago
parent
commit
6a6049220d

+ 19
- 51
App.js View File

@@ -5,7 +5,7 @@ import {Platform, StatusBar} from 'react-native';
5 5
 import LocaleManager from './src/managers/LocaleManager';
6 6
 import AsyncStorageManager from "./src/managers/AsyncStorageManager";
7 7
 import CustomIntroSlider from "./src/components/Custom/CustomIntroSlider";
8
-import {Linking, SplashScreen} from 'expo';
8
+import {SplashScreen} from 'expo';
9 9
 import ThemeManager from './src/managers/ThemeManager';
10 10
 import {NavigationContainer} from '@react-navigation/native';
11 11
 import {createStackNavigator} from '@react-navigation/stack';
@@ -15,6 +15,7 @@ import {Provider as PaperProvider} from 'react-native-paper';
15 15
 import AprilFoolsManager from "./src/managers/AprilFoolsManager";
16 16
 import Update from "./src/constants/Update";
17 17
 import ConnectionManager from "./src/managers/ConnectionManager";
18
+import URLHandler from "./src/utils/URLHandler";
18 19
 
19 20
 type Props = {};
20 21
 
@@ -43,11 +44,13 @@ export default class App extends React.Component<Props, State> {
43 44
 
44 45
     navigatorRef: Object;
45 46
 
46
-    defaultRoute: Array<string>;
47
+    defaultRoute: string | null;
47 48
     defaultData: Object;
48 49
 
49 50
     createDrawerNavigator: Function;
50 51
 
52
+    urlHandler: URLHandler;
53
+
51 54
     constructor() {
52 55
         super();
53 56
         LocaleManager.initTranslations();
@@ -55,61 +58,25 @@ export default class App extends React.Component<Props, State> {
55 58
         this.onUpdateTheme = this.onUpdateTheme.bind(this);
56 59
         SplashScreen.preventAutoHide();
57 60
         this.navigatorRef = React.createRef();
58
-        this.defaultRoute = [];
61
+        this.defaultRoute = null;
59 62
         this.defaultData = {};
60
-        // this.defaultRoute = ["main", "home", "club-information"];
61
-        // this.defaultData = {clubId: 0};
62
-        this.handleUrls();
63
-    }
64
-
65
-    handleUrls() {
66
-        console.log(Linking.makeUrl('main/home/club-information', {clubId: 1}));
67
-        Linking.addEventListener('url', this.onUrl);
68
-        Linking.parseInitialURLAsync().then(this.onParsedUrl);
63
+        this.urlHandler = new URLHandler(this.onInitialURLParsed, this.onDetectURL);
64
+        this.urlHandler.listen();
69 65
     }
70 66
 
71
-    onUrl = (url: string) => {
72
-        this.onParsedUrl(Linking.parse(url));
67
+    onInitialURLParsed = ({route, data}: Object) => {
68
+        this.defaultRoute = route;
69
+        this.defaultData = data;
73 70
     };
74 71
 
75
-    onParsedUrl = ({path, queryParams}: Object) => {
76
-        if (path !== null) {
77
-            let pathArray = path.split('/');
78
-            if (this.isClubInformationLink(pathArray))
79
-                this.handleClubInformationUrl(queryParams);
80
-            else if (this.isPlanningInformationLink(pathArray))
81
-                this.handlePlanningInformationUrl(queryParams);
82
-        }
72
+    onDetectURL = ({route, data}: Object) => {
73
+        // Navigate to nested navigator and pass data to the index screen
74
+        this.navigatorRef.current.navigate('home', {
75
+            screen: 'index',
76
+            params: {nextScreen: route, data: data, shouldOpen: true}
77
+        });
83 78
     };
84 79
 
85
-    isClubInformationLink(pathArray: Array<string>) {
86
-        return pathArray[0] === "main" && pathArray[1] === "home" && pathArray[2] === "club-information";
87
-    }
88
-
89
-    isPlanningInformationLink(pathArray: Array<string>) {
90
-        return pathArray[0] === "main" && pathArray[1] === "home" && pathArray[2] === "planning-information";
91
-    }
92
-
93
-    handleClubInformationUrl(params: Object) {
94
-        if (params !== undefined && params.clubId !== undefined) {
95
-            let id = parseInt(params.clubId);
96
-            if (!isNaN(id)) {
97
-                this.defaultRoute = ["main", "home", "club-information"];
98
-                this.defaultData = {clubId: id};
99
-            }
100
-        }
101
-    }
102
-
103
-    handlePlanningInformationUrl(params: Object) {
104
-        if (params !== undefined && params.eventId !== undefined) {
105
-            let id = parseInt(params.eventId);
106
-            if (!isNaN(id)) {
107
-                this.defaultRoute = ["main", "home", "planning-information"];
108
-                this.defaultData = {eventId: id};
109
-            }
110
-        }
111
-    }
112
-
113 80
     /**
114 81
      * Updates the theme
115 82
      */
@@ -156,7 +123,8 @@ export default class App extends React.Component<Props, State> {
156 123
         } catch (e) {
157 124
         }
158 125
 
159
-        this.createDrawerNavigator = () => <DrawerNavigator defaultPath={this.defaultRoute} defaultData={this.defaultData}/>;
126
+        this.createDrawerNavigator = () => <DrawerNavigator defaultRoute={this.defaultRoute}
127
+                                                            defaultData={this.defaultData}/>;
160 128
         this.onLoadFinished();
161 129
     }
162 130
 

+ 2
- 2
src/managers/ConnectionManager.js View File

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

+ 3
- 13
src/navigation/DrawerNavigator.js View File

@@ -317,35 +317,25 @@ function getDrawerContent(props) {
317 317
 }
318 318
 
319 319
 type Props = {
320
-    defaultPath: Array<string>,
320
+    defaultRoute: string | null,
321 321
     defaultData: Object
322 322
 }
323 323
 
324 324
 
325 325
 export default class DrawerNavigator extends React.Component<Props> {
326 326
 
327
-    defaultRoute: string;
328
-    defaultSubRoute: string | null;
329
-
330 327
     createTabNavigator: Object;
331 328
 
332 329
     constructor(props: Object) {
333 330
         super(props);
334
-        this.defaultRoute = 'Main';
335
-        this.defaultSubRoute = null;
336
-
337
-        if (props.defaultPath.length > 0)
338
-            this.defaultRoute = props.defaultPath[0];
339
-        if (props.defaultPath.length > 1)
340
-            this.defaultSubRoute = props.defaultPath[1];
341 331
 
342
-        this.createTabNavigator = () => <TabNavigator defaultPath={props.defaultPath} defaultData={props.defaultData}/>
332
+        this.createTabNavigator = () => <TabNavigator defaultRoute={props.defaultRoute} defaultData={props.defaultData}/>
343 333
     }
344 334
 
345 335
     render() {
346 336
         return (
347 337
             <Drawer.Navigator
348
-                initialRouteName={this.defaultRoute}
338
+                initialRouteName={'Main'}
349 339
                 headerMode={'float'}
350 340
                 backBehavior={'initialRoute'}
351 341
                 drawerType={'front'}

+ 11
- 9
src/navigation/MainTabNavigator.js View File

@@ -145,6 +145,10 @@ function PlanningStackComponent() {
145 145
 const HomeStack = createStackNavigator();
146 146
 
147 147
 function HomeStackComponent(initialRoute: string | null, defaultData: Object) {
148
+    let data;
149
+    if (initialRoute !== null)
150
+        data = {data: defaultData, nextScreen: initialRoute, shouldOpen: true};
151
+
148 152
     return (
149 153
         <HomeStack.Navigator
150 154
             initialRouteName={"index"}
@@ -161,7 +165,7 @@ function HomeStackComponent(initialRoute: string | null, defaultData: Object) {
161 165
                         headerLeft: openDrawer
162 166
                     };
163 167
                 }}
164
-                initialParams={{data: defaultData, nextScreen: initialRoute}}
168
+                initialParams={data}
165 169
             />
166 170
             <HomeStack.Screen
167 171
                 name="planning-information"
@@ -212,7 +216,7 @@ function PlanexStackComponent() {
212 216
 const Tab = createMaterialBottomTabNavigator();
213 217
 
214 218
 type Props = {
215
-    defaultPath: Array<string>,
219
+    defaultRoute: string | null,
216 220
     defaultData: Object
217 221
 }
218 222
 
@@ -221,19 +225,17 @@ class TabNavigator extends React.Component<Props>{
221 225
     createHomeStackComponent: Object;
222 226
     colors: Object;
223 227
 
228
+    defaultRoute: string;
229
+
224 230
     constructor(props) {
225 231
         super(props);
226 232
         this.colors = props.theme.colors;
227 233
         this.defaultRoute = AsyncStorageManager.getInstance().preferences.defaultStartScreen.current.toLowerCase();
228
-        this.defaultSubRoute = null;
229
-
230
-        if (props.defaultPath.length > 1)
231
-            this.defaultRoute = props.defaultPath[1];
232
-        if (props.defaultPath.length > 2)
233
-            this.defaultSubRoute = props.defaultPath[2];
234 234
 
235
+        if (props.defaultRoute !== null)
236
+            this.defaultRoute = 'home';
235 237
 
236
-        this.createHomeStackComponent = () => HomeStackComponent(this.defaultSubRoute, props.defaultData);
238
+        this.createHomeStackComponent = () => HomeStackComponent(props.defaultRoute, props.defaultData);
237 239
     }
238 240
 
239 241
     render() {

+ 1
- 0
src/screens/Amicale/Clubs/ClubDisplayScreen.js View File

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

+ 9
- 4
src/screens/HomeScreen.js View File

@@ -14,6 +14,7 @@ import {openBrowser} from "../utils/WebBrowser";
14 14
 import ActionsDashBoardItem from "../components/Home/ActionsDashboardItem";
15 15
 import HeaderButton from "../components/Custom/HeaderButton";
16 16
 import ConnectionManager from "../managers/ConnectionManager";
17
+import {CommonActions} from '@react-navigation/native';
17 18
 // import DATA from "../dashboard_data.json";
18 19
 
19 20
 
@@ -52,9 +53,6 @@ class HomeScreen extends React.Component<Props> {
52 53
         this.colors = props.theme.colors;
53 54
 
54 55
         this.isLoggedIn = null;
55
-        if (this.props.route.params.nextScreen !== undefined && this.props.route.params.nextScreen !== null) {
56
-            this.props.navigation.navigate(this.props.route.params.nextScreen, this.props.route.params.data);
57
-        }
58 56
     }
59 57
 
60 58
     /**
@@ -79,7 +77,14 @@ class HomeScreen extends React.Component<Props> {
79 77
                 headerRight: this.getHeaderButton,
80 78
             });
81 79
         }
82
-
80
+        // TODO if already on home screen
81
+        if (this.props.route.params !== undefined) {
82
+            if (this.props.route.params.shouldOpen !== undefined && this.props.route.params.shouldOpen) {
83
+                this.props.navigation.navigate(this.props.route.params.nextScreen, this.props.route.params.data);
84
+                // reset params to prevent infinite loop
85
+                this.props.navigation.dispatch(CommonActions.setParams({ shouldOpen: false }));
86
+            }
87
+        }
83 88
     };
84 89
 
85 90
     getHeaderButton = () => {

+ 76
- 0
src/utils/URLHandler.js View File

@@ -0,0 +1,76 @@
1
+// @flow
2
+
3
+import {Linking} from 'expo';
4
+
5
+export default class URLHandler {
6
+
7
+    static CLUB_INFO_ROUTE = "club-information";
8
+    static EVENT_INFO_ROUTE = "planning-information";
9
+
10
+    onInitialURLParsed: Function;
11
+    onDetectURL: Function;
12
+
13
+    constructor(onInitialURLParsed: Function, onDetectURL: Function) {
14
+        this.onInitialURLParsed = onInitialURLParsed;
15
+        this.onDetectURL = onDetectURL;
16
+    }
17
+
18
+    listen() {
19
+        console.log(Linking.makeUrl('main/home/club-information', {clubId: 1}));
20
+        Linking.addEventListener('url', this.onUrl);
21
+        Linking.parseInitialURLAsync().then(this.onInitialUrl);
22
+    }
23
+
24
+    onUrl = ({url}: Object) => {
25
+        let data = this.getUrlData(Linking.parse(url));
26
+        if (data !== null)
27
+            this.onDetectURL(data);
28
+    };
29
+
30
+    onInitialUrl = ({path, queryParams}: Object) => {
31
+        let data = this.getUrlData({path, queryParams});
32
+        if (data !== null)
33
+            this.onInitialURLParsed(data);
34
+    };
35
+
36
+    getUrlData({path, queryParams}: Object) {
37
+        let data = null;
38
+        if (path !== null) {
39
+            let pathArray = path.split('/');
40
+            if (this.isClubInformationLink(pathArray))
41
+                data = this.generateClubInformationData(queryParams);
42
+            else if (this.isPlanningInformationLink(pathArray))
43
+                data = this.generatePlanningInformationData(queryParams);
44
+        }
45
+        return data;
46
+    }
47
+
48
+    isClubInformationLink(pathArray: Array<string>) {
49
+        return pathArray[0] === "main" && pathArray[1] === "home" && pathArray[2] === "club-information";
50
+    }
51
+
52
+    isPlanningInformationLink(pathArray: Array<string>) {
53
+        return pathArray[0] === "main" && pathArray[1] === "home" && pathArray[2] === "planning-information";
54
+    }
55
+
56
+    generateClubInformationData(params: Object): Object | null {
57
+        if (params !== undefined && params.clubId !== undefined) {
58
+            let id = parseInt(params.clubId);
59
+            if (!isNaN(id)) {
60
+                return {route: URLHandler.CLUB_INFO_ROUTE, data: {clubId: id}};
61
+            }
62
+        }
63
+        return null;
64
+    }
65
+
66
+    generatePlanningInformationData(params: Object): Object | null {
67
+        if (params !== undefined && params.eventId !== undefined) {
68
+            let id = parseInt(params.eventId);
69
+            if (!isNaN(id)) {
70
+                return {route: URLHandler.EVENT_INFO_ROUTE, data: {eventId: id}};
71
+            }
72
+        }
73
+        return null;
74
+    }
75
+
76
+}

Loading…
Cancel
Save