2021-09-13 20:41:05 +00:00
|
|
|
import { all, delay, put, select, take, takeLatest } from 'redux-saga/effects';
|
2018-07-10 13:40:32 +00:00
|
|
|
|
2020-08-19 17:14:22 +00:00
|
|
|
import UserPreferences from '../lib/userPreferences';
|
2019-01-31 16:08:38 +00:00
|
|
|
import Navigation from '../lib/Navigation';
|
2018-05-07 20:43:26 +00:00
|
|
|
import * as types from '../actions/actionsTypes';
|
2020-07-24 15:41:59 +00:00
|
|
|
import { selectServerRequest, serverInitAdd } from '../actions/server';
|
2021-09-13 20:41:05 +00:00
|
|
|
import { inviteLinksRequest, inviteLinksSetToken } from '../actions/inviteLinks';
|
2019-09-16 20:26:32 +00:00
|
|
|
import database from '../lib/database';
|
2018-05-07 20:43:26 +00:00
|
|
|
import RocketChat from '../lib/rocketchat';
|
2018-10-23 21:39:48 +00:00
|
|
|
import EventEmitter from '../utils/events';
|
2021-09-23 14:17:53 +00:00
|
|
|
import { ROOT_INSIDE, ROOT_OUTSIDE, appInit, appStart } from '../actions/app';
|
2020-05-08 17:04:37 +00:00
|
|
|
import { localAuthenticate } from '../utils/localAuthentication';
|
2020-06-15 14:00:46 +00:00
|
|
|
import { goRoom } from '../utils/goRoom';
|
2021-03-31 21:01:20 +00:00
|
|
|
import { loginRequest } from '../actions/login';
|
2021-06-07 17:27:15 +00:00
|
|
|
import log from '../utils/log';
|
2018-05-07 20:43:26 +00:00
|
|
|
|
2018-12-21 10:55:35 +00:00
|
|
|
const roomTypes = {
|
2021-09-13 20:41:05 +00:00
|
|
|
channel: 'c',
|
|
|
|
direct: 'd',
|
|
|
|
group: 'p',
|
|
|
|
channels: 'l'
|
2018-12-21 10:55:35 +00:00
|
|
|
};
|
|
|
|
|
2020-01-28 13:22:35 +00:00
|
|
|
const handleInviteLink = function* handleInviteLink({ params, requireLogin = false }) {
|
|
|
|
if (params.path && params.path.startsWith('invite/')) {
|
|
|
|
const token = params.path.replace('invite/', '');
|
|
|
|
if (requireLogin) {
|
|
|
|
yield put(inviteLinksSetToken(token));
|
|
|
|
} else {
|
|
|
|
yield put(inviteLinksRequest(token));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-03-05 16:10:21 +00:00
|
|
|
const popToRoot = function popToRoot({ isMasterDetail }) {
|
|
|
|
if (isMasterDetail) {
|
|
|
|
Navigation.navigate('DrawerNavigator');
|
|
|
|
} else {
|
|
|
|
Navigation.navigate('RoomsListView');
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-03-12 16:23:06 +00:00
|
|
|
const navigate = function* navigate({ params }) {
|
2020-06-15 14:00:46 +00:00
|
|
|
yield put(appStart({ root: ROOT_INSIDE }));
|
2021-03-31 21:01:20 +00:00
|
|
|
if (params.path || params.rid) {
|
|
|
|
let type;
|
|
|
|
let name;
|
2021-10-26 16:11:50 +00:00
|
|
|
let jumpToThreadId;
|
2021-03-31 21:01:20 +00:00
|
|
|
if (params.path) {
|
2021-10-26 16:11:50 +00:00
|
|
|
// Following this pattern: {channelType}/{channelName}/thread/{threadId}
|
|
|
|
[type, name, , jumpToThreadId] = params.path.split('/');
|
2021-03-31 21:01:20 +00:00
|
|
|
}
|
|
|
|
if (type !== 'invite' || params.rid) {
|
2020-04-09 05:27:00 +00:00
|
|
|
const room = yield RocketChat.canOpenRoom(params);
|
|
|
|
if (room) {
|
2020-06-15 14:00:46 +00:00
|
|
|
const item = {
|
2020-04-09 05:27:00 +00:00
|
|
|
name,
|
|
|
|
t: roomTypes[type],
|
|
|
|
roomUserId: RocketChat.getUidDirectMessage(room),
|
|
|
|
...room
|
2020-06-15 14:00:46 +00:00
|
|
|
};
|
2021-03-05 16:10:21 +00:00
|
|
|
|
|
|
|
const isMasterDetail = yield select(state => state.app.isMasterDetail);
|
|
|
|
const focusedRooms = yield select(state => state.room.rooms);
|
2021-05-26 17:24:54 +00:00
|
|
|
const jumpToMessageId = params.messageId;
|
2021-03-05 16:10:21 +00:00
|
|
|
|
|
|
|
if (focusedRooms.includes(room.rid)) {
|
|
|
|
// if there's one room on the list or last room is the one
|
|
|
|
if (focusedRooms.length === 1 || focusedRooms[0] === room.rid) {
|
2021-10-26 16:11:50 +00:00
|
|
|
if (jumpToThreadId) {
|
|
|
|
// With this conditional when there is a jumpToThreadId we can avoid the thread open again
|
|
|
|
// above other thread and the room could call again the thread
|
|
|
|
popToRoot({ isMasterDetail });
|
|
|
|
}
|
|
|
|
yield goRoom({ item, isMasterDetail, jumpToMessageId, jumpToThreadId });
|
2021-03-05 16:10:21 +00:00
|
|
|
} else {
|
|
|
|
popToRoot({ isMasterDetail });
|
2021-10-26 16:11:50 +00:00
|
|
|
yield goRoom({ item, isMasterDetail, jumpToMessageId, jumpToThreadId });
|
2021-03-05 16:10:21 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
popToRoot({ isMasterDetail });
|
2021-10-26 16:11:50 +00:00
|
|
|
yield goRoom({ item, isMasterDetail, jumpToMessageId, jumpToThreadId });
|
2021-03-05 16:10:21 +00:00
|
|
|
}
|
2020-07-30 17:25:52 +00:00
|
|
|
|
|
|
|
if (params.isCall) {
|
2021-02-22 21:37:13 +00:00
|
|
|
RocketChat.callJitsi(item);
|
2020-07-30 17:25:52 +00:00
|
|
|
}
|
2020-04-09 05:27:00 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
yield handleInviteLink({ params });
|
2018-05-07 20:43:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-07-30 19:41:23 +00:00
|
|
|
const fallbackNavigation = function* fallbackNavigation() {
|
|
|
|
const currentRoot = yield select(state => state.app.root);
|
|
|
|
if (currentRoot) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
yield put(appInit());
|
|
|
|
};
|
|
|
|
|
2021-06-07 17:27:15 +00:00
|
|
|
const handleOAuth = function* handleOAuth({ params }) {
|
|
|
|
const { credentialToken, credentialSecret } = params;
|
|
|
|
try {
|
2021-07-05 18:21:15 +00:00
|
|
|
yield RocketChat.loginOAuthOrSso({ oauth: { credentialToken, credentialSecret } }, false);
|
2021-06-07 17:27:15 +00:00
|
|
|
} catch (e) {
|
|
|
|
log(e);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-05-07 20:43:26 +00:00
|
|
|
const handleOpen = function* handleOpen({ params }) {
|
2020-07-30 17:25:52 +00:00
|
|
|
const serversDB = database.servers;
|
2021-02-26 16:25:51 +00:00
|
|
|
const serversCollection = serversDB.get('servers');
|
2018-06-01 21:57:05 +00:00
|
|
|
|
2018-07-10 13:40:32 +00:00
|
|
|
let { host } = params;
|
2020-07-30 17:25:52 +00:00
|
|
|
if (params.isCall && !host) {
|
|
|
|
const servers = yield serversCollection.query().fetch();
|
|
|
|
// search from which server is that call
|
|
|
|
servers.forEach(({ uniqueID, id }) => {
|
|
|
|
if (params.path.includes(uniqueID)) {
|
|
|
|
host = id;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-06-07 17:27:15 +00:00
|
|
|
if (params.type === 'oauth') {
|
|
|
|
yield handleOAuth({ params });
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-07-30 19:41:23 +00:00
|
|
|
// If there's no host on the deep link params and the app is opened, just call appInit()
|
2020-07-30 17:25:52 +00:00
|
|
|
if (!host) {
|
2020-07-30 19:41:23 +00:00
|
|
|
yield fallbackNavigation();
|
2020-07-30 17:25:52 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-07-30 19:41:23 +00:00
|
|
|
|
|
|
|
// If there's host, continue
|
2018-07-10 13:40:32 +00:00
|
|
|
if (!/^(http|https)/.test(host)) {
|
2021-03-31 21:01:20 +00:00
|
|
|
if (/^localhost(:\d+)?/.test(host)) {
|
2021-09-13 20:41:05 +00:00
|
|
|
host = `http://${host}`;
|
2021-03-31 21:01:20 +00:00
|
|
|
} else {
|
2021-09-13 20:41:05 +00:00
|
|
|
host = `https://${host}`;
|
2021-03-31 21:01:20 +00:00
|
|
|
}
|
2020-07-30 19:41:23 +00:00
|
|
|
} else {
|
|
|
|
// Notification should always come from https
|
|
|
|
host = host.replace('http://', 'https://');
|
2018-07-10 13:40:32 +00:00
|
|
|
}
|
|
|
|
// remove last "/" from host
|
|
|
|
if (host.slice(-1) === '/') {
|
|
|
|
host = host.slice(0, host.length - 1);
|
|
|
|
}
|
2018-05-07 20:43:26 +00:00
|
|
|
|
2018-12-07 17:47:50 +00:00
|
|
|
const [server, user] = yield all([
|
2020-08-19 17:14:22 +00:00
|
|
|
UserPreferences.getStringAsync(RocketChat.CURRENT_SERVER),
|
2021-09-13 20:41:05 +00:00
|
|
|
UserPreferences.getStringAsync(`${RocketChat.TOKEN_KEY}-${host}`)
|
2018-12-07 17:47:50 +00:00
|
|
|
]);
|
2018-07-10 13:40:32 +00:00
|
|
|
|
2018-05-07 20:43:26 +00:00
|
|
|
// TODO: needs better test
|
|
|
|
// if deep link is from same server
|
2019-11-27 20:52:49 +00:00
|
|
|
if (server === host && user) {
|
|
|
|
const connected = yield select(state => state.server.connected);
|
|
|
|
if (!connected) {
|
2020-05-08 17:04:37 +00:00
|
|
|
yield localAuthenticate(host);
|
2019-11-27 20:52:49 +00:00
|
|
|
yield put(selectServerRequest(host));
|
2020-05-13 18:57:54 +00:00
|
|
|
yield take(types.LOGIN.SUCCESS);
|
2018-07-10 13:40:32 +00:00
|
|
|
}
|
2019-11-27 20:52:49 +00:00
|
|
|
yield navigate({ params });
|
2018-12-07 17:47:50 +00:00
|
|
|
} else {
|
2018-05-07 20:43:26 +00:00
|
|
|
// search if deep link's server already exists
|
2019-09-16 20:26:32 +00:00
|
|
|
try {
|
2021-03-05 16:10:21 +00:00
|
|
|
const hostServerRecord = yield serversCollection.find(host);
|
|
|
|
if (hostServerRecord && user) {
|
2020-05-08 17:04:37 +00:00
|
|
|
yield localAuthenticate(host);
|
2021-03-05 16:10:21 +00:00
|
|
|
yield put(selectServerRequest(host, hostServerRecord.version, true, true));
|
2020-01-28 13:22:35 +00:00
|
|
|
yield take(types.LOGIN.SUCCESS);
|
2019-09-16 20:26:32 +00:00
|
|
|
yield navigate({ params });
|
2019-03-18 18:52:38 +00:00
|
|
|
return;
|
|
|
|
}
|
2019-09-16 20:26:32 +00:00
|
|
|
} catch (e) {
|
|
|
|
// do nothing?
|
|
|
|
}
|
|
|
|
// if deep link is from a different server
|
2019-11-27 20:52:49 +00:00
|
|
|
const result = yield RocketChat.getServerInfo(host);
|
2019-09-16 20:26:32 +00:00
|
|
|
if (!result.success) {
|
2020-07-30 19:41:23 +00:00
|
|
|
// Fallback to prevent the app from being stuck on splash screen
|
|
|
|
yield fallbackNavigation();
|
2019-09-16 20:26:32 +00:00
|
|
|
return;
|
2018-05-07 20:43:26 +00:00
|
|
|
}
|
2021-09-23 14:17:53 +00:00
|
|
|
yield put(appStart({ root: ROOT_OUTSIDE }));
|
2020-07-24 15:41:59 +00:00
|
|
|
yield put(serverInitAdd(server));
|
2019-09-16 20:26:32 +00:00
|
|
|
yield delay(1000);
|
|
|
|
EventEmitter.emit('NewServer', { server: host });
|
2019-11-27 20:52:49 +00:00
|
|
|
|
|
|
|
if (params.token) {
|
|
|
|
yield take(types.SERVER.SELECT_SUCCESS);
|
2021-03-31 21:01:20 +00:00
|
|
|
yield put(loginRequest({ resume: params.token }, true));
|
2020-05-13 18:57:54 +00:00
|
|
|
yield take(types.LOGIN.SUCCESS);
|
|
|
|
yield navigate({ params });
|
2020-01-28 13:22:35 +00:00
|
|
|
} else {
|
|
|
|
yield handleInviteLink({ params, requireLogin: true });
|
2019-11-27 20:52:49 +00:00
|
|
|
}
|
2018-05-07 20:43:26 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const root = function* root() {
|
|
|
|
yield takeLatest(types.DEEP_LINKING.OPEN, handleOpen);
|
|
|
|
};
|
|
|
|
export default root;
|