[FIX] Deep linking between multiple logged servers (#730)
This commit is contained in:
parent
b8eb75748b
commit
477311f84a
74
app/index.js
74
app/index.js
|
@ -6,6 +6,7 @@ import { Provider } from 'react-redux';
|
|||
import { useScreens } from 'react-native-screens'; // eslint-disable-line import/no-unresolved
|
||||
import { Linking } from 'react-native';
|
||||
|
||||
import { appInit } from './actions';
|
||||
import { deepLinkingOpen } from './actions/deepLinking';
|
||||
import OnboardingView from './views/OnboardingView';
|
||||
import NewServerView from './views/NewServerView';
|
||||
|
@ -39,30 +40,25 @@ import OAuthView from './views/OAuthView';
|
|||
import SetUsernameView from './views/SetUsernameView';
|
||||
import { HEADER_BACKGROUND, HEADER_TITLE, HEADER_BACK } from './constants/colors';
|
||||
import parseQuery from './lib/methods/helpers/parseQuery';
|
||||
import { initializePushNotifications } from './push';
|
||||
import { initializePushNotifications, onNotification } from './push';
|
||||
import store from './lib/createStore';
|
||||
|
||||
useScreens();
|
||||
initializePushNotifications();
|
||||
|
||||
const handleOpenURL = ({ url }) => {
|
||||
const parseDeepLinking = (url) => {
|
||||
if (url) {
|
||||
url = url.replace(/rocketchat:\/\/|https:\/\/go.rocket.chat\//, '');
|
||||
const regex = /^(room|auth)\?/;
|
||||
if (url.match(regex)) {
|
||||
url = url.replace(regex, '');
|
||||
const params = parseQuery(url);
|
||||
store.dispatch(deepLinkingOpen(params));
|
||||
url = url.replace(regex, '').trim();
|
||||
if (url) {
|
||||
return parseQuery(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
Linking
|
||||
.getInitialURL()
|
||||
.then(url => handleOpenURL({ url }))
|
||||
.catch(e => console.warn(e));
|
||||
Linking.addEventListener('url', handleOpenURL);
|
||||
|
||||
const defaultHeader = {
|
||||
headerStyle: {
|
||||
backgroundColor: HEADER_BACKGROUND
|
||||
|
@ -184,12 +180,48 @@ const App = createAppContainer(createSwitchNavigator(
|
|||
}
|
||||
));
|
||||
|
||||
export default () => (
|
||||
<Provider store={store}>
|
||||
<App
|
||||
ref={(navigatorRef) => {
|
||||
Navigation.setTopLevelNavigator(navigatorRef);
|
||||
}}
|
||||
/>
|
||||
</Provider>
|
||||
);
|
||||
export default class Root extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.init();
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.listenerTimeout = setTimeout(() => {
|
||||
Linking.addEventListener('url', ({ url }) => {
|
||||
const parsedDeepLinkingURL = parseDeepLinking(url);
|
||||
if (parsedDeepLinkingURL) {
|
||||
store.dispatch(deepLinkingOpen(parsedDeepLinkingURL));
|
||||
}
|
||||
});
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
clearTimeout(this.listenerTimeout);
|
||||
}
|
||||
|
||||
init = async() => {
|
||||
const [notification, deepLinking] = await Promise.all([initializePushNotifications(), Linking.getInitialURL()]);
|
||||
const parsedDeepLinkingURL = parseDeepLinking(deepLinking);
|
||||
if (notification) {
|
||||
onNotification(notification);
|
||||
} else if (parsedDeepLinkingURL) {
|
||||
store.dispatch(deepLinkingOpen(parsedDeepLinkingURL));
|
||||
} else {
|
||||
store.dispatch(appInit());
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Provider store={store}>
|
||||
<App
|
||||
ref={(navigatorRef) => {
|
||||
Navigation.setTopLevelNavigator(navigatorRef);
|
||||
}}
|
||||
/>
|
||||
</Provider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import PushNotification from './push';
|
|||
import store from '../lib/createStore';
|
||||
import { deepLinkingOpen } from '../actions/deepLinking';
|
||||
|
||||
const onNotification = (notification) => {
|
||||
export const onNotification = (notification) => {
|
||||
if (notification) {
|
||||
const data = notification.getData();
|
||||
if (data) {
|
||||
|
@ -31,13 +31,11 @@ const onNotification = (notification) => {
|
|||
}
|
||||
};
|
||||
|
||||
const getDeviceToken = () => PushNotification.getDeviceToken();
|
||||
const setBadgeCount = count => PushNotification.setBadgeCount(count);
|
||||
const initializePushNotifications = () => {
|
||||
PushNotification.configure({
|
||||
export const getDeviceToken = () => PushNotification.getDeviceToken();
|
||||
export const setBadgeCount = count => PushNotification.setBadgeCount(count);
|
||||
export const initializePushNotifications = () => {
|
||||
setBadgeCount();
|
||||
return PushNotification.configure({
|
||||
onNotification
|
||||
});
|
||||
setBadgeCount();
|
||||
};
|
||||
|
||||
export { initializePushNotifications, getDeviceToken, setBadgeCount };
|
||||
|
|
|
@ -25,12 +25,7 @@ class PushNotification {
|
|||
this.onRegister = params.onRegister;
|
||||
this.onNotification = params.onNotification;
|
||||
NotificationsAndroid.refreshToken();
|
||||
|
||||
PendingNotifications.getInitialNotification()
|
||||
.then((notification) => {
|
||||
this.onNotification(notification);
|
||||
})
|
||||
.catch(e => console.warn(e));
|
||||
return PendingNotifications.getInitialNotification();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ class PushNotification {
|
|||
this.onNotification = params.onNotification;
|
||||
|
||||
NotificationsIOS.consumeBackgroundQueue();
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
export default new PushNotification();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { AsyncStorage } from 'react-native';
|
||||
import { delay } from 'redux-saga';
|
||||
import {
|
||||
takeLatest, take, select, put, all, race
|
||||
takeLatest, take, select, put, all
|
||||
} from 'redux-saga/effects';
|
||||
|
||||
import Navigation from '../lib/Navigation';
|
||||
|
@ -10,28 +10,25 @@ import { selectServerRequest } from '../actions/server';
|
|||
import database from '../lib/realm';
|
||||
import RocketChat from '../lib/rocketchat';
|
||||
import EventEmitter from '../utils/events';
|
||||
import { appStart } from '../actions';
|
||||
|
||||
const roomTypes = {
|
||||
channel: 'c', direct: 'd', group: 'p'
|
||||
};
|
||||
|
||||
const navigate = function* navigate({ params }) {
|
||||
yield put(appStart('inside'));
|
||||
if (params.rid) {
|
||||
const canOpenRoom = yield RocketChat.canOpenRoom(params);
|
||||
if (canOpenRoom) {
|
||||
const [type, name] = params.path.split('/');
|
||||
yield Navigation.navigate('RoomsListView');
|
||||
Navigation.navigate('RoomView', { rid: params.rid, name, t: roomTypes[type] });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleOpen = function* handleOpen({ params }) {
|
||||
const isReady = yield select(state => state.app.ready);
|
||||
|
||||
if (!isReady) {
|
||||
yield take(types.APP.READY);
|
||||
}
|
||||
|
||||
if (!params.host) {
|
||||
return;
|
||||
}
|
||||
|
@ -54,29 +51,28 @@ const handleOpen = function* handleOpen({ params }) {
|
|||
// if deep link is from same server
|
||||
if (server === host) {
|
||||
if (user) {
|
||||
yield race({
|
||||
typing: take(types.SERVER.SELECT_SUCCESS),
|
||||
timeout: delay(3000)
|
||||
});
|
||||
const connected = yield select(state => state.server.connected);
|
||||
if (!connected) {
|
||||
yield put(selectServerRequest(host));
|
||||
yield take(types.SERVER.SELECT_SUCCESS);
|
||||
}
|
||||
yield navigate({ params });
|
||||
} else {
|
||||
yield put(appStart('outside'));
|
||||
}
|
||||
} else {
|
||||
// if deep link is from a different server
|
||||
const result = yield RocketChat.testServer(server);
|
||||
if (!result.success) {
|
||||
return;
|
||||
}
|
||||
|
||||
// search if deep link's server already exists
|
||||
const servers = yield database.databases.serversDB.objects('servers').filtered('id = $0', host); // TODO: need better test
|
||||
if (servers.length && user) {
|
||||
yield put(selectServerRequest(host));
|
||||
yield race({
|
||||
typing: take(types.SERVER.SELECT_SUCCESS),
|
||||
timeout: delay(3000)
|
||||
});
|
||||
yield take(types.SERVER.SELECT_SUCCESS);
|
||||
yield navigate({ params });
|
||||
} else {
|
||||
// if deep link is from a different server
|
||||
const result = yield RocketChat.testServer(server);
|
||||
if (!result.success) {
|
||||
return;
|
||||
}
|
||||
Navigation.navigate('OnboardingView', { previousServer: server });
|
||||
yield delay(1000);
|
||||
EventEmitter.emit('NewServer', { server: host });
|
||||
|
|
|
@ -24,6 +24,7 @@ const handleSelectServer = function* handleSelectServer({ server }) {
|
|||
yield put(actions.appStart('inside'));
|
||||
} else {
|
||||
RocketChat.connect({ server });
|
||||
yield put(actions.appStart('outside'));
|
||||
}
|
||||
|
||||
const settings = database.objects('settings');
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
import React from 'react';
|
||||
import { StyleSheet, Image } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import StatusBar from '../containers/StatusBar';
|
||||
import { isAndroid } from '../utils/deviceInfo';
|
||||
import { appInit as appInitAction } from '../actions';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
image: {
|
||||
|
@ -14,25 +11,9 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
@connect(null, dispatch => ({
|
||||
appInit: () => dispatch(appInitAction())
|
||||
}))
|
||||
export default class Loading extends React.PureComponent {
|
||||
static propTypes = {
|
||||
appInit: PropTypes.func
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
props.appInit();
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<StatusBar />
|
||||
{isAndroid ? <Image source={{ uri: 'launch_screen' }} style={styles.image} /> : null}
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
export default React.memo(() => (
|
||||
<React.Fragment>
|
||||
<StatusBar />
|
||||
{isAndroid ? <Image source={{ uri: 'launch_screen' }} style={styles.image} /> : null}
|
||||
</React.Fragment>
|
||||
));
|
||||
|
|
|
@ -1606,7 +1606,6 @@
|
|||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = chat.rocket.reactnative;
|
||||
PRODUCT_NAME = RocketChatRN;
|
||||
PROVISIONING_PROFILE = "573947ae-c3f2-425e-aa82-0181297becf9";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "match Development chat.rocket.reactnative";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
|
@ -1653,8 +1652,7 @@
|
|||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = chat.rocket.reactnative;
|
||||
PRODUCT_NAME = RocketChatRN;
|
||||
PROVISIONING_PROFILE = "c630cec9-82b4-44ed-a9c1-922232f9dd1f";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "match AppStore chat.rocket.reactnative";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "match AppStore chat.rocket.reactnative 1552925104";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Release;
|
||||
|
|
Loading…
Reference in New Issue