Verified Commit 430f784b authored by Gijs Hendriksen's avatar Gijs Hendriksen Committed by Sébastiaan Versteeg
Browse files

Add deep linking functionality to the app

parent daadb241
......@@ -25,6 +25,15 @@
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="thalia.nu" />
<data android:path="/pizzas/" />
<data android:pathPrefix="/events/" />
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity"/>
......
export const DEEPLINK = 'DEEPLINKING_DEEPLINK';
export function deepLink(url) {
return {
type: DEEPLINK,
payload: { url },
};
}
import React, { Component } from 'react';
import { AsyncStorage } from 'react-native';
import { AsyncStorage, Linking, Platform } from 'react-native';
import { applyMiddleware, combineReducers, createStore } from 'redux';
import { Provider } from 'react-redux';
import createSagaMiddleware from 'redux-saga';
......@@ -11,6 +11,7 @@ import * as reducers from './reducers';
import sagas from './sagas';
import ReduxNavigator from './components/navigator';
import * as loginActions from './actions/login';
import * as deepLinkingActions from './actions/deepLinking';
import { register } from './actions/pushNotifications';
const sagaMiddleware = createSagaMiddleware();
......@@ -64,8 +65,28 @@ class Main extends Component {
store.dispatch(register());
}
});
this.addDeepLinkingHandler();
}
componentWillUnmount() {
Linking.removeEventListener('url', this.handleOpenURL);
}
addDeepLinkingHandler = () => {
if (Platform.OS === 'android') {
Linking.getInitialURL().then((url) => {
store.dispatch(deepLinkingActions.deepLink(url));
});
} else {
Linking.addEventListener('url', this.handleOpenURL);
}
};
handleOpenURL = (event) => {
store.dispatch(deepLinkingActions.deepLink(event.url));
};
render() {
return (
<Provider store={store}>
......
import { put, take, takeEvery, select } from 'redux-saga/effects';
import { url as siteURL, loggedInSelector } from '../url';
import * as deepLinkingActions from '../actions/deepLinking';
import * as pizzaActions from '../actions/pizza';
import * as loginActions from '../actions/login';
import * as eventActions from '../actions/event';
import * as navigationActions from '../actions/navigation';
const parseURL = (url) => {
const matches = new RegExp(`^${siteURL}(/[^?]+)(?:\\?(.+))?`).exec(url);
if (!matches) {
return {
path: '',
params: {},
};
}
const path = matches[1];
const params = {};
if (matches[2]) {
const pairs = matches[2].split('&');
for (let i = 0; i < pairs.length; i += 1) {
const pair = pairs[i].split('=');
params[pair[0]] = pair[1];
}
}
return { path, params };
};
const deepLink = function* deepLink(action) {
const { url } = action.payload;
if (!url) {
return;
}
const { path } = parseURL(url);
const loggedIn = yield select(loggedInSelector);
if (!loggedIn) {
yield take(loginActions.SUCCESS);
}
const patterns = [
{
regexp: new RegExp('^/pizzas/$'),
action: pizzaActions.retrievePizzaInfo,
args: [],
},
{
regexp: new RegExp('^/events/([0-9]+)/$'),
action: eventActions.event,
args: [],
},
{
regexp: new RegExp('^/events/$'),
action: navigationActions.navigate,
args: ['eventList'],
},
];
for (let i = 0; i < patterns.length; i += 1) {
const pattern = patterns[i];
const matches = pattern.regexp.exec(path);
if (matches) {
yield put(pattern.action(...matches.slice(1), ...pattern.args));
return;
}
}
};
const deepLinkingSaga = function* deepLinkingSaga() {
yield takeEvery(deepLinkingActions.DEEPLINK, deepLink);
};
export default deepLinkingSaga;
......@@ -8,6 +8,7 @@ import calendarSaga from './calendar';
import pushNotificationsSaga from './pushNotifications';
import pizzaSaga from './pizza';
import registrationSaga from './registration';
import deepLinkingSaga from './deepLinking';
const sagas = function* sagas() {
yield all([
......@@ -19,6 +20,7 @@ const sagas = function* sagas() {
fork(pushNotificationsSaga),
fork(pizzaSaga),
fork(registrationSaga),
fork(deepLinkingSaga),
]);
};
......
......@@ -8,6 +8,7 @@ export const apiUrl = `${server}/api/v1`;
export const pizzaUrl = 'https://pizza.thalia.nu';
export const defaultProfileImage = `${server}/static/members/images/default-avatar.jpg`;
export const tokenSelector = state => state.session.token;
export const loggedInSelector = state => state.navigation.loggedIn;
export class ServerError extends Error {
constructor(message, response) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment